/* ============================================================================
   THE SEARCH INTERFACE SYSTEM · v2 · search-interface.css
   ----------------------------------------------------------------------------
   The kit every Search product copies. Implements
   brand-marketing/brand/design-system/search-interface-system.md verbatim:
   when this file and that document disagree, THIS FILE WINS and the document
   gets fixed. Sourced from the reference builds named in the spec's header:
     Flow register        ~/Code/baja-memories (Step.tsx, index.css)
     Workspace register   ~/Code/search-wx/web-next (style.css) and
                           ~/Code/scott-os/design/round-2/work.html (shell) +
                           round-3/property.html, round-3/inventory.html

   RULES BAKED INTO THIS FILE, NOT JUST DOCUMENTED:
   - Every colour is rgb(var(--token) / alpha). No hex outside the token block.
   - Accent is a hint. The ONLY filled accent in this file is .si-primary and
     the "now" marker on a chart. Selection everywhere else is a ring + a tint.
   - Everything is rem so the four densities (14/15/17/20px root) scale type,
     padding and gaps together. The only px values in this file are 1px
     hairlines and the 44px floor inside a max() tap-target rule.
   - Two guarded dark blocks (prefers-color-scheme AND [data-theme="dark"]) so
     an explicit toggle always wins over the OS setting, in both directions.
   - Zero em dashes anywhere in this file, comments included: a period, a
     comma or a colon instead, same as every UI string the kit renders.
   ============================================================================ */

/* ── Type: self-hosted, so the page makes no third-party font request ──────
   Inter for UI and body, Space Grotesk for titles and big numbers, IBM Plex
   Mono for eyebrows, times, footnote marks and source citations. Declared
   ranges checked against the real variable-font axis with fontTools (see
   fonts/README.md): Search Clima declared Space Grotesk 500-600, which would
   have clamped v2's Space-Grotesk-400 titles to 600 with no warning. Widened
   here to the range the system actually uses, not the range one product used. */
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 400 700; font-display: swap;
  src: url("fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Space Grotesk"; font-style: normal; font-weight: 400 600; font-display: swap;
  src: url("fonts/space-grotesk-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("fonts/ibm-plex-mono-500-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Mono"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("fonts/ibm-plex-mono-600-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ── Tokens: light, then both dark guards ───────────────────────────────────
   Colour is space-separated RGB so it composes with alpha: rgb(var(--x) / .5).
   The dark block appears TWICE on purpose: once behind a prefers-color-scheme
   media guard (so a plain OS dark mode works with zero JS) and once behind
   :root[data-theme="dark"] (so a page's own toggle wins even when the OS
   disagrees). :not([data-theme="light"]) on the media-guarded block is what
   lets an explicit LIGHT choice beat a dark OS, the direction the bare media
   query alone cannot cover. */
:root {
  color-scheme: light;
  --paper:         235 234 229;
  --paper-card:    244 242 236;   /* cards are LIGHTER than the page, both themes */
  --paper-border:  220 218 212;
  --ink:             0   0   0;
  --ink-muted:      68  68  66;
  --ink-subtle:    104 102 98;    /* v2: was 110 108 104 (4.35:1, failed AA). 4.76:1 now. */
  --accent:        129  37 217;
  --accent-subtle: 235 222 238;
  --accent-on:     255 255 255;
  --ok:             22 101  74;
  --warn:          138  96  20;   /* v2 meaning: a person has not confirmed this yet */
  --danger:        155  42  30;   /* v2 meaning: overdue, at risk, destructive */
  --shade:           0   0   0;   /* shadow base only. Never a surface or a text colour. */
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --paper:           0   0   0;
    --paper-card:     19  15  21;
    --paper-border:   43  39  44;
    --ink:           255 255 255;
    --ink-muted:     203 202 204;
    --ink-subtle:    138 136 140;
    --accent:        217 255  42;
    --accent-subtle:  35  34  23;
    --accent-on:       0   0   0;
    --ok:             74 199 155;   /* own dark value: light --ok drops to ~3:1 on near-black */
    --warn:          224 179  84;
    --danger:        240 122 105;
    --shade:           0   0   0;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --paper:           0   0   0;
  --paper-card:     19  15  21;
  --paper-border:   43  39  44;
  --ink:           255 255 255;
  --ink-muted:     203 202 204;
  --ink-subtle:    138 136 140;
  --accent:        217 255  42;
  --accent-subtle:  35  34  23;
  --accent-on:       0   0   0;
  --ok:             74 199 155;
  --warn:          224 179  84;
  --danger:        240 122 105;
  --shade:           0   0   0;
}

/* ── Z-index: a scale, never a number picked to "just get on top" ──────────
   Page chrome starts past 1000 because map libraries (Leaflet) hard-code
   panes up to 1000; media chrome (a pill or legend floating over a map or a
   photo) only has to clear its OWN media, so it lives in the 400s with room
   to spare under page chrome. Every stacked surface in this file cites one
   of these names; none of them invents its own number. */
:root {
  --z-base:          1;   /* skeletons under media */
  --z-media-chrome: 410;   /* pills, legends, timelines over a map or media */
  --z-media-note:   420;   /* a note over that chrome */
  --z-header:      1010;   /* sticky top bar */
  --z-tabbar:      1015;   /* bottom tab bar */
  --z-scrim:       1020;   /* backdrop behind a popover or sheet */
  --z-popover:     1030;   /* menus, popovers, sheets */
  --z-toast:       1040;   /* the toast, always top-most */
}

/* ── Layout constants ────────────────────────────────────────────────────── */
:root {
  --si-safe-t: env(safe-area-inset-top, 0px);
  --si-safe-b: env(safe-area-inset-bottom, 0px);
  --si-tap: max(44px, 2.75rem);      /* the one physical floor: a thumb is 44px at any density */
  --si-gutter: max(16px, 1rem);
  --si-tabbar-h: 4rem;
  --si-ease: cubic-bezier(.22, .7, .3, 1);
  --si-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --si-grotesk: "Space Grotesk", Inter, sans-serif;
  --si-sans: Inter, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

/* ── Density: root font-size on <html data-density>. Everything below reads
   rem, so the layout actually grows, not just the letters. Enormous is a
   real accessibility setting, not a joke option: half this system's users
   are on a phone in direct sun. ────────────────────────────────────────── */
:root[data-density="small"]    { font-size: 14px; }
:root[data-density="medium"]   { font-size: 15px; }
:root[data-density="large"]    { font-size: 17px; }
:root[data-density="enormous"] { font-size: 20px; }

/* ── Motion: keyframes + utilities ──────────────────────────────────────────
   Steps and views replace each other; motion is what tells you something
   changed. Every animation here appears in spec section 11 by name. */
@keyframes si-rise    { from { opacity: 0; transform: translateY(.6rem); } to { opacity: 1; transform: none; } }
@keyframes si-fade    { from { opacity: 0; } to { opacity: 1; } }
@keyframes si-spin    { to { transform: rotate(360deg); } }
@keyframes si-pulse   { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@keyframes si-breathe { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@keyframes si-ring    { 0% { box-shadow: 0 0 0 0 rgb(var(--danger) / .35); } 100% { box-shadow: 0 0 0 .35rem rgb(var(--danger) / 0); } }
@keyframes si-sheet-up   { from { opacity: 0; transform: translateY(2rem); } to { opacity: 1; transform: none; } }
@keyframes si-sheet-side { from { opacity: 0; transform: translateX(2rem); } to { opacity: 1; transform: none; } }

.si-step-in { animation: si-rise .34s var(--si-ease) both; }
.si-fade-in { animation: si-fade .5s ease both; }
/* Stagger children without hand-writing a delay on each one. Capped at the
   fifth child: a sixth item arrives with the fifth's delay, never later, so a
   long list does not keep visibly loading. */
.si-stagger > * { animation: si-rise .38s var(--si-ease) both; }
.si-stagger > *:nth-child(1) { animation-delay: .04s; }
.si-stagger > *:nth-child(2) { animation-delay: .10s; }
.si-stagger > *:nth-child(3) { animation-delay: .16s; }
.si-stagger > *:nth-child(4) { animation-delay: .22s; }
.si-stagger > *:nth-child(n+5) { animation-delay: .28s; }

@media (prefers-reduced-motion: reduce) {
  .si-step-in, .si-fade-in, .si-stagger > * { animation: none !important; }
  .si-spin { animation: none !important; opacity: .6; }
  .si-skel { animation: none !important; }
  .si-strip-dot.is-danger { animation: none !important; }
  .si-live { animation: none !important; }
  .si-sheet, .si-popover { animation: si-fade .15s ease both !important; }
  * { transition-duration: .01ms !important; scroll-behavior: auto !important; }
}

/* ── Base / reset ────────────────────────────────────────────────────────── */
* { box-sizing: border-box; }
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; min-height: 100dvh;
  background: rgb(var(--paper)); color: rgb(var(--ink));
  font-family: var(--si-sans);
  font-size: 1rem; line-height: 1.55;
  -webkit-font-smoothing: antialiased; -webkit-tap-highlight-color: transparent;
}
/* While a sheet is open the page scrolls nowhere: the sheet owns the scroll. */
body.si-sheet-open { overflow: hidden; }
:focus-visible { outline: 2px solid rgb(var(--accent)); outline-offset: 2px; border-radius: .25rem; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; padding: 0; }
input, textarea, select { font: inherit; color: inherit; }
p, h1, h2, h3, h4, ol, ul, dl, dd, figure, blockquote { margin: 0; }
ol, ul { padding: 0; list-style: none; }
a { color: inherit; }
img, svg { max-width: 100%; }
.si-num { font-variant-numeric: tabular-nums; }
.si-vh {
  position: absolute !important; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; padding: 0; margin: -1px;
}
.si-ic { width: 1em; height: 1em; flex-shrink: 0; vertical-align: -.125em; display: inline-block; }

/* Autofill guard, on every login field, normal case not an edge case: Chrome
   paints its own background over a field it filled from the password manager
   and wins over `background`, so a dark theme shows two pale boxes mid-card
   unless the fix is an inset shadow the size of the field plus a very long
   background-color transition so the yellow flash never gets to paint. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
textarea:-webkit-autofill {
  -webkit-text-fill-color: rgb(var(--ink));
  -webkit-box-shadow: 0 0 0 1000px rgb(var(--paper-card)) inset;
  box-shadow: 0 0 0 1000px rgb(var(--paper-card)) inset;
  caret-color: rgb(var(--ink));
  transition: background-color 9999s ease-in-out 0s;
}

/* ── Typography roles (spec section 4) ──────────────────────────────────────
   Every role a UI string can take. Components below mostly reuse these
   directly rather than redeclaring font-family/size in the component rule. */
.si-eyebrow {
  font-family: var(--si-mono); font-weight: 500; font-size: .6667rem;
  letter-spacing: .16em; text-transform: uppercase; color: rgb(var(--accent));
}
.si-label {
  font-family: var(--si-sans); font-weight: 600; font-size: .6875rem;
  letter-spacing: .12em; text-transform: uppercase; color: rgb(var(--ink-subtle));
}
.si-title {
  font-family: var(--si-grotesk); font-weight: 400;
  font-size: clamp(1.7rem, 4.5vw, 2.15rem); line-height: 1.12; letter-spacing: -.02em;
  color: rgb(var(--ink)); text-wrap: balance; margin-top: .75rem;
}
.si-stack-title {
  font-family: var(--si-grotesk); font-weight: 400;
  font-size: 1.45rem; line-height: 1.15; letter-spacing: -.015em;
  color: rgb(var(--ink)); text-wrap: balance; margin-top: .6rem;
}
/* A step or a sheet moves focus to its own title (tabindex="-1") purely so a
   screen reader announces it; the title is not interactive, so it takes the
   same outline:none the sheet title already gets, never a visible ring. */
.si-title:focus, .si-stack-title:focus { outline: none; }
.si-lede {
  font-family: var(--si-sans); font-weight: 400; font-size: 1rem; line-height: 1.625;
  color: rgb(var(--ink-muted)); max-width: 46ch; margin-top: 1rem; text-wrap: pretty;
}
.si-meta { font-family: var(--si-sans); font-weight: 400; font-size: .875rem; line-height: 1.45; color: rgb(var(--ink-muted)); }
.si-big {
  font-family: var(--si-grotesk); font-weight: 500; font-size: 2rem; line-height: 1.1;
  letter-spacing: -.02em; color: rgb(var(--ink));
}
.si-mid {
  font-family: var(--si-grotesk); font-weight: 500; font-size: 1.35rem; line-height: 1.15;
  letter-spacing: -.01em; color: rgb(var(--ink));
}
.si-unit { font-size: .55em; font-weight: 400; letter-spacing: 0; color: rgb(var(--ink-muted)); margin-left: .15em; }
.si-src { margin: .8rem 0 0; font-size: .6875rem; line-height: 1.4; color: rgb(var(--ink-subtle)); }
.si-src a, .si-quote cite { text-decoration: underline; text-underline-offset: .15em; }

/* ── Layout: frames, gutters, tap, the page grid ────────────────────────────
   Frames are centred with auto margins, never `align-items: center` on the
   surrounding flex/grid, so content taller than the viewport top-aligns and
   scrolls instead of centring itself off the top of the screen. */
.si-frame {
  width: 100%; margin-inline: auto;
  padding-inline: var(--si-gutter);
}
.si-frame--flow      { max-width: 41.33rem; }
.si-frame--wide       { max-width: 58.67rem; }
.si-frame--deck       { max-width: 74.67rem; }
.si-frame--workspace { max-width: 75rem; }
.si-frame--rail       { max-width: 86.667rem; }

/* Workspace page: main column + a side rail, switched on by a CONTAINER query
   on the page itself, never viewport width, so an embedded or split view
   collapses correctly regardless of the outer window. Below the threshold the
   rail drops under main because it is already last in DOM order. */
.si-page { container: si-page / inline-size; padding-block: 1.25rem 2rem; }
.si-page-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1.75rem; }
@container si-page (min-width: 54rem) {
  .si-page-grid--rail {
    grid-template-columns: minmax(0, 1fr) minmax(15rem, 22rem);
    column-gap: 2.5rem; row-gap: 2rem; align-items: start;
  }
  .si-page-grid--rail > .si-rail-slot { align-self: start; }
}
.si-col { display: flex; flex-direction: column; gap: 1rem; min-width: 0; }

/* ── Top bar ─────────────────────────────────────────────────────────────── */
.si-topbar {
  position: sticky; top: 0; z-index: var(--z-header);
  background: rgb(var(--paper) / .94); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border-bottom: 1px solid rgb(var(--paper-border));
}
.si-topbar-in {
  max-width: 86.667rem; margin-inline: auto; padding: .85rem var(--si-gutter);
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem;
}
.si-brand {
  display: inline-flex; align-items: center; gap: .5rem; min-height: var(--si-tap);
  text-decoration: none; color: rgb(var(--ink)); flex-shrink: 0;
}
/* si-brand-lockup: the icon + SEARCH wordmark, inlined from
   assets/logo/svt-lockup-h-short.inline.svg, currentColor so it swaps with the
   theme token for free. This IS the logo; never rebuild it from the mark plus
   a typed name (CLAUDE.md Hard Line 6). A product or section name is a
   separate si-label beside it, never inside the lockup's own markup. */
.si-brand-lockup { height: 1.3rem; flex-shrink: 0; display: inline-flex; color: rgb(var(--ink)); }
.si-brand-lockup svg { display: block; height: 100%; width: auto; }
.si-brand-mark { width: 1.3rem; height: 1.3rem; flex-shrink: 0; display: inline-flex; color: rgb(var(--ink)); }
.si-brand-mark svg { display: block; width: 100%; height: 100%; }
.si-brand-section { margin-left: .3rem; }

/* Pill nav: where am I, top level. Active takes the Choice treatment (accent
   text + tint + inset ring) because it names a place, not a destination you
   are about to leave. */
.si-nav { display: flex; gap: .25rem; flex-wrap: wrap; }
.si-nav a {
  display: inline-flex; align-items: center; gap: .45rem; min-height: var(--si-tap);
  padding: .45rem .95rem; border-radius: 999px; font-size: .85rem; color: rgb(var(--ink-muted));
  text-decoration: none; transition: color .2s ease, background-color .2s ease;
}
.si-nav a:hover { color: rgb(var(--ink)); background: rgb(var(--paper-border) / .35); }
.si-nav a[aria-current="page"] {
  color: rgb(var(--accent)); background: rgb(var(--accent-subtle));
  box-shadow: inset 0 0 0 1px rgb(var(--accent));
}
.si-nav .si-ic { width: 1.05rem; height: 1.05rem; }

.si-status { display: flex; align-items: center; gap: .75rem; font-size: .8rem; color: rgb(var(--ink-muted)); margin-left: auto; }
.si-status-live { display: inline-flex; align-items: center; gap: .5rem; }
.si-live { width: .5rem; height: .5rem; border-radius: 999px; background: rgb(var(--accent)); flex-shrink: 0; animation: si-breathe 2.4s ease-in-out infinite; }

.si-avatar {
  width: 1.9rem; height: 1.9rem; border-radius: 999px; flex-shrink: 0;
  display: inline-grid; place-items: center; font-size: .75rem; font-weight: 700;
  background: rgb(var(--paper)); color: rgb(var(--ink)); box-shadow: 0 0 0 1px rgb(var(--paper-border));
}
/* The agent's avatar is tinted accent-subtle; the person's own stays neutral.
   The accent marks the agent, never the human at the keyboard. */
.si-avatar--agent { background: rgb(var(--accent-subtle)); color: rgb(var(--accent)); box-shadow: 0 0 0 1px rgb(var(--accent) / .35); }

/* View tabs: which view of this section. Underline, not a pill: it sets a
   sub-position within a place the pill nav already named. */
.si-tabs { display: flex; gap: 1.4rem; align-items: stretch; border-bottom: 1px solid rgb(var(--paper-border)); }
.si-tabs a {
  display: inline-flex; align-items: center; gap: .45rem; min-height: var(--si-tap);
  font-size: .9rem; font-weight: 500; color: rgb(var(--ink-muted)); text-decoration: none;
  border-bottom: 2px solid transparent; margin-bottom: -1px; padding: .2rem 0; transition: color .15s ease;
}
.si-tabs a:hover { color: rgb(var(--ink)); }
.si-tabs a[aria-current="page"] { color: rgb(var(--ink)); font-weight: 600; border-bottom-color: rgb(var(--accent)); }

/* ── Bottom tab bar (phone): replaces the pill nav under 47.99rem ──────────
   Hidden by default; the phone media query below turns it on and hides the
   pill nav, so only one of the two navs is ever in the accessibility tree. */
.si-tabbar {
  display: none; position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-tabbar);
  background: rgb(var(--paper-card) / .97); border-top: 1px solid rgb(var(--paper-border));
  padding: .35rem .5rem calc(.35rem + var(--si-safe-b));
}
.si-tabbar-row { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); } /* any count of 3 to 5 tabs; more than 5 belongs under a "More" tab */
.si-tabbar a {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .2rem;
  min-height: var(--si-tap); font-size: .6875rem; font-weight: 500; color: rgb(var(--ink-subtle)); text-decoration: none;
  border-radius: .6rem;
}
.si-tabbar a .si-ic { font-size: 1.35rem; }
.si-tabbar a[aria-current="page"] { color: rgb(var(--ink)); }
.si-tabbar a[aria-current="page"] .si-ic { color: rgb(var(--accent)); }

/* Alert strip: a slim row under the nav, opens on a CSS grid-rows transition
   rather than height/max-height so it can go from 0 to auto without a fixed
   pixel guess. The only looping animations allowed besides spinners,
   skeletons and the live dot are the danger ring below. */
.si-strip-slot { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .35s ease; }
.si-strip-slot.is-open { grid-template-rows: 1fr; }
.si-strip-slot > div { overflow: hidden; min-height: 0; }
.si-strip {
  display: flex; align-items: center; gap: .6rem; font-size: .85rem; color: rgb(var(--ink));
  padding: .55rem var(--si-gutter); border-top: 1px solid rgb(var(--paper-border));
}
.si-strip a { margin-left: auto; font-weight: 500; white-space: nowrap; text-decoration: underline; text-underline-offset: .2em; }
.si-strip-dot { width: .5rem; height: .5rem; border-radius: 999px; background: rgb(var(--warn)); flex-shrink: 0; display: inline-block; }
.si-strip-dot.is-danger { background: rgb(var(--danger)); animation: si-ring 1.8s ease-out infinite; }

/* ── Controls ────────────────────────────────────────────────────────────── */
.si-primary, .si-secondary {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: var(--si-tap); padding: .7rem 1.75rem; border-radius: 999px; border: 1px solid transparent;
  font-size: .95rem; font-weight: 500; line-height: 1.2; white-space: nowrap; text-decoration: none;
  transition: opacity .18s ease, background-color .35s ease, color .35s ease, border-color .35s ease;
}
.si-primary { background: rgb(var(--accent)); color: rgb(var(--accent-on)); }
.si-primary:hover { opacity: .9; }
.si-primary:disabled { opacity: .4; cursor: not-allowed; }
.si-primary[aria-busy="true"]:disabled { opacity: .85; cursor: progress; }
/* Secondary (Scott's "queued"): same geometry, no fill, so a sequence of
   not-yet-current actions never competes with the one filled Primary.
   .is-next marks the one that is up without promoting it to a fill. */
.si-secondary { background: transparent; color: rgb(var(--ink)); border-color: rgb(var(--paper-border)); }
.si-secondary:hover { border-color: rgb(var(--ink-muted)); }
.si-secondary.is-next { border-color: rgb(var(--ink) / .7); font-weight: 500; }
/* One filled Primary per screen state: while a sheet is open, the page BEHIND
   it gives up its fill so only the sheet's own Primary stays filled. Bind
   this by putting .si-sheet-open on <body> when a sheet opens. */
body.si-sheet-open .si-page .si-primary { background: transparent; color: rgb(var(--ink)); border-color: rgb(var(--paper-border)); }

.si-quiet {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  min-height: var(--si-tap); padding: .75rem 1rem; border-radius: 999px; border: 0; background: transparent;
  font-size: .9rem; color: rgb(var(--ink-muted)); text-decoration: none; white-space: nowrap;
  transition: color .2s ease;
}
.si-quiet:hover { color: rgb(var(--ink)); }
.si-quiet:disabled { opacity: .4; cursor: default; }
/* Back is a Quiet with a chevron, left-aligned negative margin so its text
   lines up with the content below it rather than its own tap padding. */
.si-back { margin: -.6rem 0 .4rem -1rem; }
.si-back .si-ic { margin-right: -.1rem; }

.si-iconbtn {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 2.25rem; height: 2.25rem; border-radius: 999px; border: 1px solid rgb(var(--paper-border));
  background: rgb(var(--paper-card)); color: rgb(var(--ink)); font-size: 1rem;
  transition: border-color .15s ease;
}
.si-iconbtn:hover { border-color: rgb(var(--ink-subtle)); }

/* Choice: a tile, never a fill. Selection is a border + a tinted ground + a
   1px ring, the same three-part treatment a filter chip uses in pill form. */
.si-choice {
  display: flex; width: 100%; flex-direction: column; align-items: flex-start; gap: .25rem;
  min-height: var(--si-tap); padding: 1rem; text-align: left; border-radius: .75rem;
  border: 1px solid rgb(var(--paper-border)); background: rgb(var(--paper-card));
  transition: border-color .2s ease, background-color .2s ease, box-shadow .2s ease;
}
.si-choice:hover { border-color: rgb(var(--ink-muted)); }
.si-choice[aria-pressed="true"] {
  border-color: rgb(var(--accent)); background: rgb(var(--accent-subtle)); box-shadow: 0 0 0 1px rgb(var(--accent));
}
.si-choice-title { font-family: var(--si-grotesk); font-size: 1.05rem; letter-spacing: -.01em; line-height: 1.25; color: rgb(var(--ink)); }
.si-choice-note { font-size: .8rem; line-height: 1.4; color: rgb(var(--ink-muted)); }
.si-choices { display: grid; gap: .75rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr)); }
.si-choices--one { grid-template-columns: minmax(0, 1fr); }
.si-choices--pair { grid-template-columns: repeat(auto-fit, minmax(min(100%, 8.5rem), 1fr)); }

/* Segmented: a mode switch, not a destination, so the selected segment is
   PAPER fill + an ink ring, never accent. ES/EN, S/M/L/XL, that kind of pick. */
.si-seg {
  display: inline-flex; align-items: center; gap: .15rem; padding: .2rem;
  border: 1px solid rgb(var(--paper-border)); border-radius: 999px; background: rgb(var(--paper-card));
}
.si-seg button {
  display: inline-flex; align-items: center; justify-content: center; min-height: calc(var(--si-tap) - .4rem);
  border-radius: 999px; padding: .35rem .8rem; font-size: .8rem; font-weight: 500;
  color: rgb(var(--ink-muted)); white-space: nowrap; transition: color .15s ease, background-color .15s ease, box-shadow .15s ease;
}
.si-seg button:hover { color: rgb(var(--ink)); }
.si-seg button[aria-pressed="true"] { color: rgb(var(--ink)); background: rgb(var(--paper)); box-shadow: inset 0 0 0 1px rgb(var(--paper-border)); }

/* Filter chip: a Choice in pill form. On is an accent ring plus a tint,
   exactly the Choice treatment, never a fill. */
.si-chip {
  display: inline-flex; align-items: center; gap: .35rem; min-height: 2.25rem; padding: .4rem 1.1rem;
  border-radius: 999px; border: 1px solid rgb(var(--paper-border)); background: rgb(var(--paper-card));
  font-size: .85rem; color: rgb(var(--ink-muted)); transition: all .2s ease;
}
.si-chip:hover { border-color: rgb(var(--ink-muted)); color: rgb(var(--ink)); }
.si-chip[aria-pressed="true"] {
  border-color: rgb(var(--accent)); background: rgb(var(--accent-subtle)); color: rgb(var(--accent));
  box-shadow: 0 0 0 1px rgb(var(--accent));
}

/* ── Tags and status ─────────────────────────────────────────────────────── */
.si-pill {
  display: inline-flex; align-items: center; vertical-align: .08em; border-radius: 999px;
  padding: .12rem .6rem; font-size: .7333rem; font-weight: 600; letter-spacing: .03em; line-height: 1.5;
  background: rgb(var(--paper-border) / .55); color: rgb(var(--ink-muted)); white-space: nowrap;
}
/* Status pills tint by meaning, never by decoration: warn = unconfirmed,
   danger = overdue or at risk, ok = done. "Not sent" on every agent draft
   uses --warn: a draft is unconfirmed by definition until a person sends it. */
.si-pill--warn   { color: rgb(var(--warn));   background: rgb(var(--warn) / .16); }
.si-pill--ok     { color: rgb(var(--ok));     background: rgb(var(--ok) / .16); }
.si-pill--danger { color: rgb(var(--danger)); background: rgb(var(--danger) / .16); }
/* accent-free: a category tag that rides a title with no status meaning at
   all, so it stays on the neutral ground even though accent is available. */
.si-pill--accent-free { color: rgb(var(--ink-muted)); background: rgb(var(--paper-border) / .55); }

.si-prov {
  display: inline-flex; align-items: center; gap: .3rem; border-radius: 999px;
  border: 1px solid rgb(var(--paper-border)); padding: .1rem .5rem; font-size: .6875rem;
  line-height: 1.5; color: rgb(var(--ink-muted)); white-space: nowrap; background: rgb(var(--paper));
}
.si-prov .si-ic { font-size: .75rem; }

/* ── Inputs ──────────────────────────────────────────────────────────────── */
.si-field, .si-input {
  display: block; width: 100%; min-height: var(--si-tap);
  border: 1px solid rgb(var(--paper-border)); border-radius: .6rem; background: rgb(var(--paper-card));
  padding: .7rem .85rem; font: inherit; font-size: max(16px, 1rem); color: rgb(var(--ink));
}
.si-field::placeholder, .si-input::placeholder { color: rgb(var(--ink-subtle)); }
.si-field:focus, .si-input:focus {
  outline: none; border-color: rgb(var(--accent)); box-shadow: 0 0 0 3px rgb(var(--accent) / .18);
}
.si-field-error { margin: .5rem 0 0; font-size: .8rem; color: rgb(var(--danger)); min-height: 1.4em; }
.si-hint { margin: .55rem 0 0; font-size: .82rem; color: rgb(var(--ink-muted)); min-height: 1.4em; display: flex; align-items: center; gap: .45rem; }

/* Search field: a hairline card until you touch it, then an accent border.
   :focus-within so clicking the icon or the field both light the border. */
.si-search {
  display: flex; align-items: center; gap: .5rem; min-height: var(--si-tap);
  border: 1px solid rgb(var(--paper-border)); border-radius: .7rem; padding: .5rem .7rem;
  background: rgb(var(--paper-card)); color: rgb(var(--ink-subtle));
}
.si-search input { flex: 1; min-width: 0; border: 0; background: none; font-size: .9rem; color: rgb(var(--ink)); }
.si-search input::placeholder { color: rgb(var(--ink-subtle)); }
.si-search input:focus { outline: none; }
.si-search:focus-within { border-color: rgb(var(--accent)); }

/* Code input (OTP): one field, spaced out, monospace so every digit is the
   same width, autocomplete="one-time-code" lets iOS/Android autofill an SMS. */
.si-code {
  letter-spacing: .5em; text-align: center; font-family: var(--si-mono); font-size: 1.25rem;
}
/* A field group's own rhythm, so a page never hand-writes a spacer between a
   label and the input it labels. */
.si-label + .si-field, .si-label + .si-input, .si-hint + .si-label { margin-top: .5rem; }
.si-resend { margin-top: .5rem; padding-left: 0; font-size: .85rem; color: rgb(var(--ink-subtle)); }

/* ── Feedback ────────────────────────────────────────────────────────────── */
/* Skeleton: the EXACT geometry of the filled state, filled in place, never
   rebuilt. text goes transparent rather than removed so nothing reflows when
   the real value lands. */
.si-skel {
  color: transparent !important; background: rgb(var(--paper-border)); border-radius: .35rem;
  animation: si-pulse 1.6s ease-in-out infinite;
}
.si-skel * { visibility: hidden; }

.si-spin { animation: si-spin .8s linear infinite; will-change: transform; flex-shrink: 0; }

/* Pending: setPending() in si.js locks the button's width in rem BEFORE the
   spinner goes in, so the label swap never changes the button's footprint
   and a density change mid-flight still scales it correctly. */
.si-primary.is-pending, .si-secondary.is-pending, .si-quiet.is-pending { cursor: progress; }
.si-primary[aria-busy="true"]:disabled, .si-secondary[aria-busy="true"]:disabled { opacity: .85; }
.si-pending-label { display: inline-block; }

.si-toast {
  position: fixed; left: 50%; bottom: 1.5rem; transform: translate(-50%, .5rem);
  background: rgb(var(--ink)); color: rgb(var(--paper)); padding: .6rem 1.1rem;
  border-radius: 999px; font-size: .85rem; opacity: 0; pointer-events: none; max-width: calc(100vw - 2rem);
  transition: opacity .25s ease, transform .25s ease; z-index: var(--z-toast); white-space: nowrap; text-overflow: ellipsis; overflow: hidden;
}
.si-toast.is-visible { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }

/* Inline retry: the message and the retry button live INSIDE the card that
   failed, so the rest of the page keeps working while one region is down. */
.si-retry { margin-top: .5rem; display: flex; align-items: center; gap: .5rem; font-size: .82rem; color: rgb(var(--ink-muted)); flex-wrap: wrap; }
.si-retry .si-quiet { padding: .4rem .8rem; border: 1px solid rgb(var(--paper-border)); min-height: 0; }

/* ── The card: the workspace's base unit (spec section 8) ───────────────────
   Fixed anatomy top to bottom: head (icon + Label, optional provenance chip
   pushed right), body, then a source line that is ALWAYS last and prefilled
   before the network answers so the card never re-wraps when data lands.
   `container: si-stack` names the containment context every row/fact/gallery
   query below keys off, so a Row or a Fact grid collapses correctly inside
   ANY card variant, not just `.si-stack` itself. */
.si-card {
  container: si-stack / inline-size;
  background: rgb(var(--paper-card)); border: 1px solid rgb(var(--paper-border)); border-radius: .875rem;
  padding: 1.1rem 1.2rem .9rem; display: flex; flex-direction: column; min-width: 0;
  transition: border-color .3s ease, box-shadow .3s ease;
}
/* Generic reveal target: si.js's light()/reveal() can point at ANY card
   (not just a Stack or a Needs-you, which get their own stronger variant
   below), so every card answers .is-lit the same way a row does. */
.si-card.is-lit { border-color: rgb(var(--accent)); box-shadow: 0 0 0 1px rgb(var(--accent)); }
.si-card-head { display: flex; align-items: center; gap: .5rem; min-height: 1.4rem; flex-wrap: wrap; }
.si-card-head .si-ic { font-size: .9rem; color: rgb(var(--ink-muted)); }
.si-card-head .si-label { display: inline-flex; align-items: center; gap: .45rem; }
.si-card-head .si-prov { margin-left: auto; }
.si-card-body { margin-top: .7rem; flex: 1; }
/* Decision cards (Stack, Needs you) get more room to breathe than data cards. */
.si-card--decision { padding: 1.75rem; }

/* ── Brief: the agent's note, each sentence footnoted to the row it is about ─
   Source: Scott's .note/.brief, Clima's .wx-report sentence list. */
.si-brief { padding: 1.35rem 1.5rem 1.25rem; }
.si-brief-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; padding-bottom: .9rem; border-bottom: 1px dashed rgb(var(--paper-border)); }
.si-brief-head .si-when { font-family: var(--si-mono); font-size: .75rem; color: rgb(var(--ink-subtle)); }
.si-brief-text {
  margin-top: 1rem; max-width: 60ch; font-family: var(--si-grotesk); font-weight: 400;
  font-size: 1.3rem; line-height: 1.55; letter-spacing: -.01em; text-wrap: pretty; color: rgb(var(--ink));
}
/* A footnoted sentence: underlined in a tint of the accent so it reads as a
   link into the page, not as emphasis on the words themselves. */
.si-s {
  text-decoration: underline; text-decoration-color: rgb(var(--accent) / .38);
  text-decoration-thickness: .09em; text-underline-offset: .22em; border-radius: .3rem;
  transition: background-color .2s ease, text-decoration-color .2s ease, color .3s ease;
  -webkit-box-decoration-break: clone; box-decoration-break: clone; color: inherit; text-decoration-line: underline;
}
.si-s:hover, .si-s.is-hint { text-decoration-color: rgb(var(--accent)); background: rgb(var(--accent-subtle)); }
/* A sentence whose row is cleared goes quiet: still tappable, it still finds the row. */
.si-s.is-done { color: rgb(var(--ink-subtle)); text-decoration-color: rgb(var(--ink-subtle) / .35); }
.si-fn { font-family: var(--si-mono); font-weight: 500; color: rgb(var(--accent)); letter-spacing: 0; text-decoration: none; }
.si-brief .si-fn { font-size: .55em; vertical-align: .75em; line-height: 0; margin-left: .15em; }
.si-row-title .si-fn, .si-stack-title .si-fn { font-size: .62em; vertical-align: .7em; line-height: 0; margin-left: .2em; }
.si-brief-sign { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem; margin-top: 1.25rem; padding-top: 1rem; border-top: 1px dashed rgb(var(--paper-border)); }
.si-brief-sign-who { min-width: 0; flex: 1 1 9rem; }
.si-brief-sign-who b { display: block; font-weight: 500; font-size: .92rem; }
.si-brief-sign-who span { display: block; font-size: .8rem; color: rgb(var(--ink-muted)); line-height: 1.4; }
.si-brief-sign .si-quiet { margin-left: auto; padding: .5rem .25rem .5rem .75rem; font-size: .85rem; }

/* ── Metric: label, big value, context line, optional sparkline or meter ──── */
.si-metric-context { font-size: .82rem; color: rgb(var(--ink-muted)); margin-top: .2rem; }
.si-meter { margin-top: .6rem; height: .25rem; max-width: 11rem; border-radius: 999px; background: rgb(var(--paper-border)); overflow: hidden; }
.si-meter i, .si-meter-fill { display: block; height: 100%; border-radius: inherit; background: rgb(var(--warn)); }

/* ── Count: a trust ledger, dotted leaders, tabular numbers ─────────────────
   Ends with "Sent without you · 0": the count that stays at zero is the
   entire point of the card, so it always renders even when everything else
   is loading. */
.si-tally { margin-top: .8rem; }
.si-tally li { display: flex; align-items: baseline; gap: .5rem; padding: .28rem 0; font-size: .92rem; }
.si-lead { flex: 1; min-width: 1rem; border-bottom: 1px dotted rgb(var(--ink-subtle) / .6); transform: translateY(-.28em); }
.si-tally .si-v { font-family: var(--si-mono); font-size: .88rem; font-variant-numeric: tabular-nums; }
.si-tally li.si-sub { padding-left: .9rem; font-size: .84rem; color: rgb(var(--ink-muted)); }
.si-tally li.si-sub .si-v { font-size: .8rem; }
.si-tally li.si-rule { padding: 0; margin: .55rem 0; border-top: 1px solid rgb(var(--paper-border)); }
.si-count-note { margin-top: .8rem; font-size: .84rem; line-height: 1.55; color: rgb(var(--ink-muted)); }

/* ── Stack: a queue, one item at a time, progress rail on top ("1 of 3") ──── */
.si-stack { padding: 1.75rem; transition: border-color .3s ease, box-shadow .3s ease; }
.si-stack.is-lit { border-color: rgb(var(--accent)); box-shadow: 0 0 0 1px rgb(var(--accent)); }

/* Rail / progress: shared by a Stack's queue header and Flow's StepFrame
   (spec: "used by Flow and by any queue card"), so the two names below carry
   IDENTICAL rules rather than drifting into two components that look alike. */
.si-rail, .si-progress {
  display: flex; gap: .75rem; margin-bottom: 1.6rem;
}
.si-rail-seg {
  flex: 1; height: 3px; border-radius: 999px; background: rgb(var(--paper-border));
  transition: background-color .5s ease;
}
.si-rail-seg.is-current { background: rgb(var(--accent) / .35); }
.si-rail-seg.is-done { background: rgb(var(--accent)); }
/* A tappable segment (jump to a step or a queue item): the button is bigger
   than the bar it wraps, so the 44px floor never shrinks the visible rail. */
.si-rail-btn {
  flex: 1; display: flex; align-items: center; min-height: var(--si-tap); margin: calc(var(--si-tap) * -.5 + 1.5px) 0;
  background: none; border: 0; border-radius: 4px;
}
.si-rail-btn:disabled { cursor: default; }

/* ── Needs you: a decision card with a hint border. The one Primary on the
   page lives here. `.is-lit` is the stronger, transient highlight a footnote
   or a deep link points a Needs-you card into, same treatment as a lit row. */
.si-needs { border-color: rgb(var(--accent) / .6); }
.si-needs.is-lit { border-color: rgb(var(--accent)); box-shadow: 0 0 0 1px rgb(var(--accent)); }

/* ── Draft: an agent-written message preview, never mistaken for sent copy ── */
.si-draft {
  margin-top: 1rem; padding: 1rem 1.15rem 1.1rem; border-radius: .75rem;
  background: rgb(var(--paper)); border: 1px solid rgb(var(--paper-border));
}
.si-draft-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .5rem; }
.si-draft-by { display: inline-flex; align-items: center; gap: .45rem; font-family: var(--si-mono); font-size: .7rem; letter-spacing: .1em; text-transform: uppercase; color: rgb(var(--ink-subtle)); }
.si-draft-by .si-ic { width: 1.15rem; height: 1.15rem; color: rgb(var(--ink-muted)); }
.si-draft-to { margin-top: .6rem; font-size: .8rem; color: rgb(var(--ink-subtle)); }
.si-draft-body {
  margin-top: .45rem; font-size: 1rem; line-height: 1.6; color: rgb(var(--ink));
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* ── Day list: rows with a mono time gutter ─────────────────────────────────
   Collapses at two container breakpoints, keyed to the CARD's own inline
   size, not the viewport: 34rem drops the action under the text, 18rem (an
   enormous phone) moves the gutter above the title so words keep their width. */
.si-rows { margin-top: 1.25rem; }
.si-row {
  display: grid; grid-template-columns: 4.5rem minmax(0, 1fr) auto; column-gap: 1rem;
  align-items: center; padding: 1rem 0; border-top: 1px solid rgb(var(--paper-border));
  border-radius: .2rem; transition: background-color .3s ease, box-shadow .3s ease;
}
.si-row:first-child { border-top: 0; padding-top: .5rem; }
.si-row:focus { outline: none; }
.si-row:focus-visible { outline: 2px solid rgb(var(--accent)); outline-offset: .4rem; }
/* Lit: the row a Brief footnote points at. A tint that reaches past the
   row's own edges without moving anything else, gone after a couple of
   seconds (si.js's reveal()). Hint is the lighter :hover preview of the same idea. */
.si-row.is-lit { background: rgb(var(--accent-subtle)); box-shadow: 0 0 0 .75rem rgb(var(--accent-subtle)), 0 0 0 calc(.75rem + 1px) rgb(var(--accent) / .5); }
.si-row.is-hint { background: rgb(var(--paper)); box-shadow: 0 0 0 .75rem rgb(var(--paper)); }
.si-gutter {
  align-self: start; padding-top: .2rem; font-family: var(--si-mono); font-size: .75rem;
  letter-spacing: .04em; color: rgb(var(--ink-subtle)); font-variant-numeric: tabular-nums;
}
.si-gutter--warn { color: rgb(var(--warn)); }
.si-gutter--danger { color: rgb(var(--danger)); }
.si-gutter .si-ic { display: block; width: 1.15rem; height: 1.15rem; color: rgb(var(--ok)); }
.si-row-title { font-weight: 500; line-height: 1.35; color: rgb(var(--ink)); }
.si-row-title .si-pill { margin-left: .35rem; }
.si-row-meta { margin-top: .2rem; font-size: .875rem; line-height: 1.45; color: rgb(var(--ink-muted)); }
.si-row.is-done .si-row-title { font-weight: 400; color: rgb(var(--ink-muted)); }
.si-row-action { justify-self: end; }
@container si-stack (max-width: 34rem) {
  .si-row { grid-template-columns: 3.75rem minmax(0, 1fr); }
  .si-row .si-row-action { grid-column: 2; justify-self: start; margin-top: .75rem; }
  .si-row.is-done { grid-template-columns: 3.75rem minmax(0, 1fr) auto; }
  .si-row.is-done .si-row-action { grid-column: auto; margin-top: 0; }
}
@container si-stack (max-width: 18rem) {
  .si-row { grid-template-columns: minmax(0, 1fr); }
  .si-row .si-gutter { padding-top: 0; margin-bottom: .2rem; }
  .si-row .si-row-action { grid-column: 1; }
  .si-row.is-done { grid-template-columns: auto minmax(0, 1fr); column-gap: .6rem; }
  .si-row.is-done .si-row-action { grid-column: 2; justify-self: start; margin-top: .25rem; }
}

/* ── Facts: a dl grid of labels over values, each with its own provenance ─── */
.si-facts { margin-top: 1.5rem; display: grid; gap: 1rem 1.25rem; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); }
.si-facts dd { margin-top: .2rem; font-family: var(--si-grotesk); font-size: 1.05rem; line-height: 1.3; letter-spacing: -.01em; color: rgb(var(--ink)); }
.si-facts .si-stamp { display: block; margin-top: .2rem; font-family: var(--si-sans); font-size: .78rem; letter-spacing: 0; color: rgb(var(--ink-muted)); }
.si-facts .is-unconfirmed { color: rgb(var(--warn)); }

/* ── Quote: copy we did not write, quoted and cited, never restyled as ours ─ */
.si-quote { margin-top: 1.75rem; padding-top: 1.5rem; border-top: 1px dashed rgb(var(--paper-border)); }
.si-quote blockquote {
  margin: .75rem 0 0; padding-left: 1rem; border-left: 2px solid rgb(var(--paper-border));
  font-family: var(--si-grotesk); font-size: 1.05rem; line-height: 1.6; color: rgb(var(--ink));
}
.si-quote cite { display: block; margin-top: .6rem; font-style: normal; font-family: var(--si-mono); font-size: .78rem; color: rgb(var(--ink-subtle)); }

/* ── Gallery: scroll-snap strip, dots + arrows, own media ringed accent ────── */
.si-gallery-wrap { padding: 1.25rem 1.25rem 1rem; min-width: 0; }
.si-gallery {
  display: flex; gap: .85rem; overflow-x: auto; scroll-snap-type: x mandatory; min-width: 0;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.si-gallery::-webkit-scrollbar { display: none; }
.si-slide { flex: 0 0 min(78%, 20rem); scroll-snap-align: center; }
.si-slide-frame {
  aspect-ratio: 4 / 3; border-radius: .85rem; display: grid; place-items: center;
  background: rgb(var(--paper)); border: 1px solid rgb(var(--paper-border)); color: rgb(var(--ink-subtle));
}
.si-slide-frame .si-ic { width: 2.5rem; height: 2.5rem; font-size: 2.5rem; }
/* Media that is ours (not the source feed's) rings accent, in both the frame
   and its caption: a hint, never a fill, that this one came from us. */
.si-slide.is-own .si-slide-frame { border-color: rgb(var(--accent) / .4); color: rgb(var(--accent)); }
.si-slide.is-own .si-slide-cap { color: rgb(var(--accent)); }
.si-slide-cap { margin: .55rem 0 0; font-family: var(--si-mono); font-size: .72rem; letter-spacing: .04em; color: rgb(var(--ink-subtle)); text-align: center; }
.si-gallery-foot { margin-top: .9rem; display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.si-gallery-dots { display: flex; gap: .4rem; }
.si-gallery-dots .si-dot { width: .5rem; height: .5rem; border-radius: 999px; border: 0; padding: 0; background: rgb(var(--paper-border)); }
.si-gallery-dots .si-dot[aria-selected="true"] { background: rgb(var(--accent)); }
.si-gallery-nav { display: flex; gap: .25rem; }
@container si-stack (max-width: 34rem) { .si-slide { flex-basis: 82%; } }

/* ── People: avatar + name + one line of context ────────────────────────── */
.si-people-row { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem; }
.si-people-row + .si-people-row { margin-top: .9rem; }
.si-people-who { min-width: 0; flex: 1 1 9rem; }
.si-people-who b { display: block; font-weight: 500; font-size: .92rem; color: rgb(var(--ink)); }
.si-people-who span { display: block; font-size: .8rem; color: rgb(var(--ink-muted)); line-height: 1.4; }
.si-avatar--neutral { background: rgb(var(--paper-border) / .6); color: rgb(var(--ink-muted)); box-shadow: none; }

/* ── Chart: inline SVG, token colours, an accent "now" marker, a visually
   hidden table twin so the same data reaches a screen reader ────────────── */
.si-chart { display: block; width: 100%; height: auto; overflow: visible; }
.si-chart-box { position: relative; height: 9.5rem; margin-top: .4rem; }
.si-chart-box svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.si-chart-line { fill: none; stroke: rgb(var(--ink-muted)); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.si-chart-line-soft { fill: none; stroke: rgb(var(--ink-subtle)); stroke-width: 1.5; stroke-dasharray: 3 3; vector-effect: non-scaling-stroke; }
.si-chart-area { fill: rgb(var(--ink-muted) / .07); stroke: none; }
.si-chart-bar { fill: rgb(var(--ink-subtle) / .35); }
.si-chart-grid { stroke: rgb(var(--paper-border)); stroke-width: 1; vector-effect: non-scaling-stroke; }
/* The "now" marker is the one place besides Primary an accent may be drawn
   as a filled shape rather than a ring: it is data (this instant), not chrome. */
.si-chart-now { stroke: rgb(var(--accent)); stroke-width: 2; vector-effect: non-scaling-stroke; }
.si-chart-now-dot { fill: rgb(var(--accent)); }
.si-chart-dot { fill: rgb(var(--ink-muted)); }
.si-chart-label { fill: rgb(var(--ink-subtle)); font-size: .68rem; font-family: Inter, sans-serif; font-variant-numeric: tabular-nums; }
.si-chart-label-strong { fill: rgb(var(--ink)); font-size: .72rem; font-weight: 600; font-family: Inter, sans-serif; font-variant-numeric: tabular-nums; }
.si-chart-ticks { display: flex; justify-content: space-between; font-size: .68rem; color: rgb(var(--ink-subtle)); margin-top: .3rem; font-variant-numeric: tabular-nums; }
.si-chart-ticks .is-now { color: rgb(var(--ink)); font-weight: 600; }

/* ── Week strip: 7 day columns, today ringed, snap-scrolls on phone ────────── */
.si-week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: .25rem; }
.si-week-day { display: flex; flex-direction: column; align-items: center; gap: .3rem; padding: .6rem .2rem; border-radius: .7rem; text-align: center; font-variant-numeric: tabular-nums; border: 1px solid transparent; }
.si-week-day.is-today { border-color: rgb(var(--accent) / .7); box-shadow: inset 0 0 0 1px rgb(var(--accent) / .35); }
.si-week-day-name { font-size: .8rem; font-weight: 600; text-transform: capitalize; }
.si-week-day-date { font-size: .7rem; color: rgb(var(--ink-subtle)); }
.si-week-day-icon { font-size: 1.5rem; color: rgb(var(--ink-muted)); height: 1.6rem; display: inline-flex; align-items: center; }
.si-week-day-max { font-size: .95rem; font-weight: 600; }
.si-week-day-min { font-size: .8rem; color: rgb(var(--ink-muted)); }
@media (max-width: 47.99rem) {
  .si-week {
    display: flex; overflow-x: auto; scroll-snap-type: x mandatory; gap: .2rem; margin: 0 -.4rem; padding: 0 .4rem;
    -webkit-mask-image: linear-gradient(90deg, rgb(var(--shade)) 85%, transparent); mask-image: linear-gradient(90deg, rgb(var(--shade)) 85%, transparent);
    scrollbar-width: none;
  }
  .si-week::-webkit-scrollbar { display: none; }
  .si-week-day { flex: 0 0 4.25rem; scroll-snap-align: start; }
}

/* ── State blocks: named, never a generic blank (spec section 10) ─────────── */
.si-empty, .si-stale, .si-error {
  padding: 1.5rem 1.1rem; text-align: center; color: rgb(var(--ink-muted)); font-size: .9rem; line-height: 1.5;
}
.si-empty .si-ic, .si-stale .si-ic, .si-error .si-ic { font-size: 1.4rem; color: rgb(var(--ink-subtle)); margin-bottom: .5rem; }
/* Stale: the numbers stay on screen, this is just the note about their age. */
.si-stale { text-align: left; display: flex; align-items: center; gap: .5rem; color: rgb(var(--ink-subtle)); font-size: .78rem; padding: .5rem 0 0; }
.si-stale .si-ic { margin-bottom: 0; color: rgb(var(--warn)); }
/* Error keeps the inline-retry grammar (message + Quiet Retry), left-aligned
   inside the card that failed, so the rest of the page keeps working. */
.si-error { text-align: left; color: rgb(var(--danger)); padding: .75rem 0 0; }
.si-error .si-ic { color: rgb(var(--danger)); margin-bottom: 0; margin-right: .4rem; }

/* ── Layered: scrim, popover, sheet ──────────────────────────────────────────
   The page behind goes `inert` (si.js), Esc closes, focus returns to the
   opener. Sheet is a bottom sheet under 900px, a right side panel from 900px. */
.si-scrim {
  position: fixed; inset: 0; z-index: var(--z-scrim); background: rgb(var(--shade) / .35);
  animation: si-fade .2s ease both;
}
.si-popover {
  position: absolute; z-index: var(--z-popover); width: 22rem; max-width: calc(100vw - 2rem);
  background: rgb(var(--paper-card)); border: 1px solid rgb(var(--paper-border)); border-radius: .9rem;
  box-shadow: 0 1rem 2.4rem rgb(var(--shade) / .18); padding: .5rem; animation: si-fade .15s ease both;
  max-height: calc(100vh - 6rem); overflow-y: auto;
}
.si-popover-label { font-size: .66rem; letter-spacing: .14em; text-transform: uppercase; color: rgb(var(--ink-subtle)); font-weight: 600; margin: .6rem .6rem .3rem; }
.si-popover-opt {
  display: flex; align-items: center; gap: .6rem; width: 100%; min-height: var(--si-tap); text-align: left;
  padding: .55rem .6rem; border-radius: .55rem; font-size: .9rem; color: rgb(var(--ink));
}
.si-popover-opt:hover, .si-popover-opt.is-active { background: rgb(var(--paper-border) / .5); }
.si-popover-opt[aria-selected="true"] { box-shadow: inset 2px 0 0 rgb(var(--accent)); }

.si-sheet {
  position: fixed; z-index: var(--z-popover); left: 0; right: 0; bottom: 0; max-height: 88dvh;
  display: flex; flex-direction: column; overflow-y: auto; overscroll-behavior: contain;
  background: rgb(var(--paper-card)); border-top: 1px solid rgb(var(--paper-border));
  border-radius: 1.25rem 1.25rem 0 0; box-shadow: 0 -1rem 3rem rgb(var(--shade) / .12);
}
.si-sheet.si-step-anim { animation: si-sheet-up .32s var(--si-ease) both; }
.si-sheet-head {
  position: sticky; top: 0; z-index: 2; display: flex; justify-content: flex-end;
  padding: .35rem .5rem 0; background: rgb(var(--paper-card));
}
.si-sheet-grip { position: absolute; left: 50%; top: .6rem; width: 2.4rem; height: .3rem; margin-left: -1.2rem; border-radius: 999px; background: rgb(var(--paper-border)); }
.si-sheet-close { min-width: var(--si-tap); min-height: var(--si-tap); padding: 0; }
.si-sheet-body { flex: 1 0 auto; display: flex; flex-direction: column; padding: 0 1.25rem 1.75rem; }
.si-sheet-title { margin-top: .75rem; }
.si-sheet-title:focus { outline: none; }
.si-sheet-meta { margin-top: .5rem; max-width: 46ch; font-size: .92rem; line-height: 1.55; color: rgb(var(--ink-muted)); }
.si-sheet-foot {
  position: sticky; bottom: 0; z-index: 2; margin: auto -1.25rem 0;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .5rem;
  padding: .9rem 1.25rem calc(.9rem + var(--si-safe-b));
  background: rgb(var(--paper-card)); border-top: 1px solid rgb(var(--paper-border));
}
.si-sheet-foot .si-primary { margin-left: auto; }
.si-sheet-foot.is-stacked { flex-direction: column; align-items: stretch; }
.si-sheet-foot.is-stacked .si-primary { margin-left: 0; width: 100%; }
.si-sheet-quiets { display: flex; flex-wrap: wrap; justify-content: space-between; gap: .25rem; }
@media (min-width: 900px) {
  .si-sheet {
    top: 0; left: auto; max-height: none; width: min(32rem, calc(100vw - 3rem));
    border-top: 0; border-left: 1px solid rgb(var(--paper-border)); border-radius: 0;
    box-shadow: -1rem 0 3rem rgb(var(--shade) / .1);
  }
  .si-sheet.si-step-anim { animation-name: si-sheet-side; }
  .si-sheet-grip { display: none; }
  .si-sheet-head { padding: .75rem .75rem 0; }
  .si-sheet-body { padding: 0 2rem 1.75rem; }
  .si-sheet-foot { margin: auto -2rem 0; padding: 1rem 2rem 1.25rem; }
  /* With the side panel open, the toast centres in what is left of the page
     so it never lands on top of the panel's own buttons. */
  body.si-sheet-open .si-toast { left: calc(50% - min(16rem, calc(50vw - 1.5rem))); }
}

/* ── Floating: the ONLY register allowed a blur + shadow, and only over media
   or as the dev tools pill. A card on plain page background never floats. ── */
.si-float {
  background: rgb(var(--paper-card) / .92); border: 1px solid rgb(var(--paper-border)); border-radius: .8rem;
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  box-shadow: 0 .6rem 1.8rem rgb(var(--shade) / .14);
}

/* ── Dev tools pill: theme + density, fixed bottom right, above the tab bar
   on phone so it never collides with the bottom nav ────────────────────── */
.si-tools {
  position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: var(--z-media-chrome);
  display: flex; gap: .15rem; padding: .2rem; border-radius: 999px;
  background: rgb(var(--paper-card) / .92); border: 1px solid rgb(var(--paper-border));
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.si-tool {
  display: inline-flex; align-items: center; gap: .35rem; min-height: 2.1rem; border: 0; background: transparent;
  border-radius: 999px; padding: .35rem .7rem; font-size: .72rem; color: rgb(var(--ink-subtle));
  transition: color .2s ease, background-color .2s ease;
}
.si-tool:hover { color: rgb(var(--ink)); background: rgb(var(--paper)); }
.si-tool .si-ic { width: .95rem; height: .95rem; }
.si-tool b { font-weight: 500; font-family: var(--si-mono); letter-spacing: .03em; }

/* ── Coda: the small agent glyph and the one line saying what this page will
   and will not do. Always the last thing on a workspace page. ────────────── */
.si-coda { display: flex; gap: .65rem; align-items: flex-start; max-width: 54ch; font-size: .85rem; line-height: 1.55; color: rgb(var(--ink-subtle)); }
.si-coda .si-ic { width: 1.15rem; height: 1.15rem; flex: none; margin-top: .1rem; }

/* ── Flow register: StepFrame (spec section 2 and baja-memories Step.tsx) ───
   Deliberately narrow, deliberately empty: no chrome, one question, one way
   forward. `margin: auto` on the frame (not `align-items: center` on the
   flex parent) is what makes tall content top-align and scroll instead of
   centring itself off the top of a short viewport. */
.si-step-page { display: flex; min-height: 100dvh; flex-direction: column; background: rgb(var(--paper)); }
.si-step-main { display: flex; flex: 1; padding-block: 2.5rem 3.5rem; }
.si-step-main > .si-frame { margin: auto; }
.si-step-content { margin-top: 2.25rem; }
.si-step-footer { margin-top: 2.5rem; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem; }
/* A step with no way back (sign-in as the landing step): the Primary sits alone. */
.si-step-footer.is-solo { justify-content: flex-end; }
.si-step-footer .si-primary { margin-left: auto; }
/* An input step's two-column layout (choices beside a live preview, say),
   never viewport math: a plain media query is fine here because the whole
   step already lives at a fixed frame width, not a fluid page column. */
.si-step-deck { display: grid; gap: 2rem; }
@media (min-width: 48rem) { .si-step-deck { grid-template-columns: minmax(16rem, 1fr) 1.6fr; align-items: start; } }

/* ── Phone: one break, 47.99rem. Top nav becomes the bottom tab bar, popovers
   become bottom sheets (sheets are already bottom sheets by default; the
   900px query above is what promotes them to a side panel on larger screens). */
@media (max-width: 47.99rem) {
  .si-hide-phone { display: none !important; }
  .si-topbar-in { padding-block: calc(.5rem + var(--si-safe-t)) .35rem; }
  .si-nav { display: none; }
  .si-tabbar { display: block; }
  body.has-si-tabbar { padding-bottom: calc(var(--si-tabbar-h) + var(--si-safe-b)); }
  .si-tabs { overflow-x: auto; scrollbar-width: none; gap: 1rem; }
  .si-tabs::-webkit-scrollbar { display: none; }
  :root[data-density="enormous"] .si-brand-section { display: none; }
  .si-card--decision, .si-stack, .si-needs { padding: 1.25rem; }
  .si-brief { padding: 1.1rem 1.15rem 1rem; }
  .si-brief-text { font-size: 1.2rem; margin-top: .6rem; }
  /* Each footnoted sentence becomes its own full-width line, a whole tap
     target at least 44px tall, rather than an inline run a thumb can miss. */
  .si-brief-text .si-s { display: block; padding: .5rem 0; min-height: var(--si-tap); border-radius: .5rem; margin: 0 -.5rem; padding-left: .5rem; padding-right: .5rem; }
  .si-brief-sign .si-quiet { min-height: var(--si-tap); }
  .si-primary, .si-secondary, .si-quiet, .si-tool, .si-rail-btn, .si-choice, .si-seg button { min-height: var(--si-tap); }
  .si-title { font-size: 2rem; line-height: 1.1; }
  .si-tools { right: var(--si-gutter); bottom: calc(var(--si-tabbar-h) + var(--si-safe-b) + .75rem); }
  .si-toast { bottom: calc(var(--si-tabbar-h) + var(--si-safe-b) + 4.5rem); }
  /* A bottom sheet open: the toast goes to the top, over the scrim, clear of the sheet's own buttons. */
  body.si-sheet-open .si-toast { top: calc(1rem + var(--si-safe-t)); bottom: auto; transform: translate(-50%, 0); }
  /* A popover collapses to a bottom sheet on phone, si.js adds .is-sheet. */
  .si-popover.is-sheet {
    position: fixed; left: 0; right: 0; bottom: 0; top: auto; width: 100%; max-width: none; max-height: 85vh;
    border-radius: 1rem 1rem 0 0; padding-bottom: calc(.8rem + var(--si-safe-b)); animation: si-sheet-up .22s ease both;
  }
  .si-page { padding-block: .9rem 1.5rem; }
  .si-page-grid { gap: 1.25rem; }
}

/* ── Narrow tier: 26.24rem, trims secondary labels only ─────────────────── */
@media (max-width: 26.24rem) {
  .si-brand-lockup { height: 1.1rem; }
  .si-status .si-hide-narrow { display: none; }
}

/* ── Print never renders app chrome: nothing here ships to a printer. ──────
   ============================================================================
   END search-interface.css
   ============================================================================ */
