/*
 * atfs.dev's shared design tokens and base element styles — the teal
 * palette and type choices the home page (web/index.html) established.
 * Linked with a stable, unhashed URL (/atfs.css) rather than bundled: the
 * bake script (hack/bake-site-downloads.sh) generates the raw-downloads
 * page after the Vite build and cannot resolve a content-hashed filename
 * without manifest plumbing.
 *
 * Every surface (home, docs, the setup flow, raw-downloads) links this and
 * layers its own page-specific rules on top — this file only carries what
 * is genuinely shared: tokens, resets, and the handful of bare elements
 * (links, code, tables, headings) that should look the same everywhere.
 */

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* The topbar (app.css) is sticky at the top of every page. Without this, a
   same-page anchor jump (the docs TOC, a `?sbc#section-id` deep link, any
   #heading link) lands its target right underneath the bar instead of
   below it — this is what the browser's own native fragment-scroll reads
   instead of a hardcoded scroll offset, so it applies uniformly to every
   way a page can land on an anchor, present or future. 5.25rem clears the
   topbar's own rendered height with a little breathing room below it —
   measured directly (Playwright) at ~69.8px/4.36rem on a wide viewport,
   where the topbar's own padding and each pill's own padding both add to
   the total; the narrow-viewport single-strip fallback (app.css's media
   query) is shorter, so the wide figure is the one that has to clear.
   (Was 6rem/~82.75px before the account pill's buttons became plain
   .nav-link text — re-measure and update this together with docs
   +layout.svelte's .docs-toc `top`, same as before, if it changes again.) */
html {
  scroll-padding-top: 5.25rem;
}

:root {
  color-scheme: light dark;

  --teal: #469ea2;
  --teal-light: #6acad1;
  --ink: #1f4647;

  --bg: #f4fafa;
  --bg-raised: #e7f3f3;
  --text: var(--ink);
  --text-dim: #4f7273;
  --border: #c7dedf;
  --accent: var(--teal);
  --accent-strong: #327478;
  --on-accent: #f4fafa;
  --danger: #b3413f;
  --good: #1a7a4c;

  /* Callout severities (Callout.svelte's five GFM-alert-style types) —
     each pairs a text/border color with its own tinted background, same
     shape as the base tokens above. */
  --note: #3576c7;
  --note-bg: #e8f1fb;
  --tip: #1a7a4c;
  --tip-bg: #e6f5ec;
  --important: #7d4fd6;
  --important-bg: #f1eafc;
  --warning: #a5760a;
  --warning-bg: #fbf1de;
  --caution: var(--danger);
  --caution-bg: #fbeae9;

  --sans:
    system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono:
    ui-monospace, "SF Mono", "Cascadia Code", "Roboto Mono", Menlo, Consolas,
    monospace;

  --edge: clamp(1.25rem, 5vw, 3rem);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #16302f;
    --bg-raised: #1d3c3b;
    --text: #dff2f2;
    --text-dim: #9dc4c4;
    --border: #2c5251;
    --accent: var(--teal-light);
    --accent-strong: #8adbe0;
    --on-accent: #12302f;
    --danger: #ff9d97;
    --good: #6fd39b;

    --note: #7db6ee;
    --note-bg: #16283c;
    --tip: #6fd39b;
    --tip-bg: #14301f;
    --important: #c3a4f5;
    --important-bg: #2a1f42;
    --warning: #e3b566;
    --warning-bg: #3a2c11;
    --caution: var(--danger);
    --caution-bg: #3a1917;
  }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 1.05rem/1.6 var(--sans);
  text-wrap: pretty;
  -webkit-font-smoothing: antialiased;
}

::selection {
  background: var(--accent);
  color: var(--on-accent);
}

a {
  color: var(--accent-strong);
}
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
  outline: 2px solid var(--accent-strong);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: absolute;
  left: -999px;
  top: auto;
}
.skip-link:focus {
  left: var(--edge);
  top: 0.75rem;
  z-index: 10;
  background: var(--bg);
  padding: 0.5rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: 0.3em;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

code,
pre {
  font-family: var(--mono);
}
code {
  font-size: 0.9em;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  padding: 0.1em 0.45em;
  border-radius: 0.3em;
  overflow-wrap: anywhere;
}
pre {
  font-size: 0.9em;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  padding: 0.9rem 1rem;
  border-radius: 0.5em;
  overflow-x: auto;
}
pre code {
  background: none;
  border: none;
  padding: 0;
}

table {
  border-collapse: collapse;
  width: 100%;
}
th,
td {
  text-align: left;
  vertical-align: top;
  padding: 0.6rem 0.75rem 0.6rem 0;
  border-bottom: 1px solid var(--border);
}
thead th {
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-dim);
  font-weight: 600;
}

.callout {
  border: 1px solid var(--border);
  background: var(--bg-raised);
  border-radius: 0.5em;
  padding: 1rem 1.1rem;
  margin: 0 0 1.25rem;
}
.callout p:last-child {
  margin-bottom: 0;
}

/* Callout.svelte's five severities — each just overrides the border and
   title color; the box shape above stays the same for all of them. */
.callout-title {
  font-weight: 600;
  margin: 0 0 0.5rem;
}

.callout-note {
  border-color: var(--note);
  background: var(--note-bg);
}
.callout-note .callout-title {
  color: var(--note);
}
.callout-tip {
  border-color: var(--tip);
  background: var(--tip-bg);
}
.callout-tip .callout-title {
  color: var(--tip);
}
.callout-important {
  border-color: var(--important);
  background: var(--important-bg);
}
.callout-important .callout-title {
  color: var(--important);
}
.callout-warning {
  border-color: var(--warning);
  background: var(--warning-bg);
}
.callout-warning .callout-title {
  color: var(--warning);
}
.callout-caution {
  border-color: var(--caution);
  background: var(--caution-bg);
}
.callout-caution .callout-title {
  color: var(--caution);
}

/* Shiki's own theme output (pre.shiki) would otherwise diverge visually
   from the plain `pre` rule above — this keeps the frame consistent and
   lets Shiki's dual-theme CSS variables drive only the token colors.
   Token background-color is deliberately never set here, even per-theme:
   Shiki emits one background per TOKEN span, and painting each one
   individually leaves small colored rectangles behind only the highlighted
   words with gaps between them, rather than one continuous block — the
   whole point of a code *block*. The single background above, on the
   pre/code box itself, is what a multi-line block actually needs.

   Only pre.shiki itself gets that background/border — never pre.shiki
   code too. <code> is an inline element wrapping all five (or however
   many) lines of a multi-line block; give an inline element its own
   border and the browser draws one around EACH line it wraps onto
   (border-radius included), not once around the whole thing — the same
   "per line" box the token-background mistake above produced, from an
   entirely different cause. The plain `pre code` rule further up already
   resets <code>'s own border/background/padding to nothing, which is all
   it needs — it was this rule re-adding a border with !important,
   specifically for Shiki blocks, that broke it again. */
pre.shiki {
  position: relative;
  background: var(--bg-raised) !important;
  border: 1px solid var(--border) !important;
}

/* The copy button codeCopy.ts adds to every code block, top right.
   Positioned against pre.shiki itself (the position: relative above), so
   it stays put regardless of the block's own horizontal scroll. A real
   <button>, not a decorative overlay: tabbing to it and pressing
   Enter/Space fires the same click the block-wide listener (below) reacts
   to, same as clicking anywhere else in the block. */
.copy-button {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.7rem;
  height: 1.7rem;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 0.35em;
  background: var(--bg);
  color: var(--text-dim);
  cursor: pointer;
}
.copy-button svg {
  width: 0.95rem;
  height: 0.95rem;
}
.copy-button:hover {
  color: var(--text);
}

/* Click feedback: inverted relative to the button's own resting colors
   above, timed from the click handler rather than :active — :active alone
   is unreliable on touch (iOS Safari needs a touch listener elsewhere on
   the page before it fires at all), where a real click event doesn't have
   that problem. */
.copy-button.copied {
  background: var(--text-dim);
  color: var(--bg);
}

.shiki span {
  color: var(--shiki-light);
}
@media (prefers-color-scheme: dark) {
  .shiki span {
    color: var(--shiki-dark);
  }
}

/* A platform-block (PlatformBlock.svelte) gets a light right-border cue —
   the same visual language as .callout's colored border, diminished: a
   thin accent line, no background tint, no title label. Right rather than
   left keeps it out of the way of .callout's own left-edge border, so a
   platform-block is never confused for one. Only one of an sbc/docker pair
   is ever visible at once (the toggle rule below), so both share one
   marker color rather than needing two. */
.platform-block {
  border-right: 3px solid color-mix(in srgb, var(--accent) 55%, transparent);
  padding-right: 0.9rem;
  margin: 0 0 1.25rem;
}
.platform-block > :last-child {
  margin-bottom: 0;
}

/* The docs platform toggle (PlatformToggle.svelte) — one of a pair is
   hidden depending on data-platform-pref, set on <html> before paint by
   the inline script in app.html. See CLAUDE.md's docs conventions. */
[data-platform-pref="sbc"] .platform-block[data-platform="docker"],
[data-platform-pref="docker"] .platform-block[data-platform="sbc"] {
  display: none;
}

/* A sidebar link for a page whose frontmatter `relevance` names one
   platform is dimmed, not hidden, while the toggle points the other way —
   the page still exists and is still reachable, it just isn't what a
   visitor currently browsing the other platform's content is looking for. */
[data-platform-pref="sbc"] .docs-nav-topic a[data-relevance="docker"],
[data-platform-pref="docker"] .docs-nav-topic a[data-relevance="sd-card"] {
  opacity: 0.45;
}

/* The banner DocLayout.svelte renders beneath a page's intro line — only
   when a visitor is currently toggled to the OTHER platform than a
   platform-exclusive page names, so it never shows to the audience the page
   was actually written for. A plain box, deliberately no accent border:
   this sits right under the intro line, in the same slot DocLayout puts a
   plain <hr> on a page the note doesn't apply to (see .doc-divider) — an
   extra colored bar here would be one more thing to tell apart from
   .callout's and .platform-block's own borders, for no real gain. */
.platform-relevance-note {
  display: none;
  border: 1px solid var(--border);
  background: var(--bg-raised);
  border-radius: 0.4em;
  padding: 0.6rem 0.9rem;
  margin: 0 0 1.5rem;
  font-size: 0.9rem;
  color: var(--text-dim);
}
[data-platform-pref="docker"] .platform-relevance-note[data-relevance="sd-card"],
[data-platform-pref="sbc"] .platform-relevance-note[data-relevance="docker"] {
  display: block;
}

/* PlatformChooser/PlatformChoice — an in-page way to change data-platform-
   pref (getting-started/+page.md is the first user), rather than only ever
   reading it the way .platform-block and the relevance note do. */
.platform-chooser {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  margin: 0 0 1.25rem;
}
@media (max-width: 30rem) {
  .platform-chooser {
    grid-template-columns: 1fr;
  }
}

.platform-choice {
  border: 1px solid var(--border);
  border-radius: 0.5em;
  padding: 1rem 1.1rem;
  cursor: pointer;
}
.platform-choice:hover {
  border-color: var(--accent-strong);
}
.platform-choice:focus-visible {
  outline: 2px solid var(--accent-strong);
  outline-offset: 2px;
}

.platform-choice-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 700;
  margin: 0 0 0.5rem;
}

/* A radio-style dot, not just a border/background color change, so the
   selected choice reads clearly without relying on color alone. */
.platform-choice-radio {
  flex: none;
  width: 0.9rem;
  height: 0.9rem;
  border-radius: 50%;
  border: 2px solid var(--border);
}

.platform-choice-body :global(p:last-child) {
  margin-bottom: 0;
}

/* Selection is purely attribute-driven, exactly like .platform-block's own
   visibility rule above — correct from first paint, no onMount correction
   needed. Deliberately never dims or fades the UNSELECTED choice: both
   stay fully readable, so either one is easy to pick. */
[data-platform-pref="sbc"] .platform-choice[data-platform="sbc"],
[data-platform-pref="docker"] .platform-choice[data-platform="docker"] {
  border-color: var(--accent);
  background: var(--bg-raised);
}
[data-platform-pref="sbc"] .platform-choice[data-platform="sbc"] .platform-choice-radio,
[data-platform-pref="docker"] .platform-choice[data-platform="docker"] .platform-choice-radio {
  border-color: var(--accent);
  background: radial-gradient(circle, var(--accent) 45%, transparent 50%);
}

/* A small brand mark linking home — used by any page whose own layout
   doesn't already put the logo front and center the way the home page's
   hero does (the docs page and raw-downloads). */
.wordmark {
  font-family: var(--sans);
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--text);
  text-decoration: none;
}
