/* Rincon greybox — shared tokens + primitives.
   Both surfaces link this file and add LAYOUT ONLY.
   A brand value in a surface file is a bug. */

@font-face { font-family:"Neue Haas Unica Pro"; font-weight:400; font-display:swap; src:url(fonts/NeueHaasUnicaPro-400.woff2) format("woff2"); }
@font-face { font-family:"Neue Haas Unica Pro"; font-weight:600; font-display:swap; src:url(fonts/NeueHaasUnicaPro-600.woff2) format("woff2"); }

:root {
  /* Surface + ink — 5 tones + 1 wash, 1 bar material, 1 hairline. */
  --bg:       #FFFFFF;
  --s1:       #F4F4F3;
  --s2:       #E6E6E4;
  --s3:       #C9C8C4;
  --ink:      #1A1A18;
  --ink-2:    #6B6A66;
  --line:     rgba(26,26,24,0.08);
  /* Wash — 2% black over the page ground, for a surface that should read as
     fractionally off-white without becoming a card. A sixth tone; the set was
     five, and this is the only thing using it. */
  --wash:     rgba(0,0,0,0.02);
  --bar:      rgba(255,255,255,0.76);
  --bar-blur: 24px;

  /* Type — 4 sizes. App uses 13/16/20/39. */
  --fs-s: 13px; --lh-s: 17px; --ls-s:  0.01em;
  --fs-b: 16px; --lh-b: 21px; --ls-b:  0;
  --fs-m: 20px; --lh-m: 30px; --ls-m: -0.01em;
  --fs-h: 39px; --lh-h: 41px; --ls-h: -0.02em;

  /* Space — 8px atom, 5 steps. 80 is a desktop section beat only. */
  --sp-1: 8px; --sp-2: 16px; --sp-3: 24px; --sp-4: 32px; --sp-5: 80px;

  /* Shape */
  --r: 16px;

  /* Bar clearance — the height of the pinned tab bar, named once here so a screen
     that has to scroll clear of it reads the same number the bar is drawn at
     instead of hard-coding its own copy. */
  --tabbar: 82px;

  /* Motion — 4 eases, no duration tokens. Durations are named per move in the specs.
     in-out is for motion that reverses: a loop that breathes both ways needs a curve
     that decelerates into each end, which the three one-directional curves cannot do. */
  --ease-out:    cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in:     cubic-bezier(0.32, 0, 0.67, 0);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --ease-settle: cubic-bezier(0.32, 0.72, 0, 1);
}

/* Inverted — the same ramp seen from the other end, for the screens that go dark
   (sage, live activity). Scoped, not a media query: darkness here is a property of
   the screen, not of the viewer's system. Every primitive below reads these vars,
   so .card/.ph/.fab/.tabbar invert for free inside it. The dark steps mirror the
   light ones's distance from their ground: 11/25/54 off white becomes 11/25/54 off ink. */
.inverted {
  --bg:    #1A1A18;
  --s1:    #252524;
  --s2:    #333331;
  --s3:    #504F4B;
  --ink:   #FFFFFF;
  --ink-2: #A8A6A0;
  --line:  rgba(255,255,255,0.10);
  --bar:   rgba(26,26,24,0.76);
  background: var(--bg); color: var(--ink);
}

* { box-sizing: border-box; margin: 0; }

body {
  font-family: "Neue Haas Unica Pro", -apple-system, sans-serif;
  font-weight: 400;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}
/* Form controls do not inherit the page face on their own — every one of them has
   to be told. `button` alone left `input` rendering in the UA's Arial, which is
   how a search field ends up in the wrong typeface on an otherwise correct screen. */
button, input, textarea, select { font-family: inherit; }

/* The app's section tier is 20/30, per Figma. The shell's own documentation
   views are a different surface — a reading measure at desktop width, where the
   same role wants the larger step — so they keep the 25/31 this used to be.
   No product page on the website uses this role at all. */
.p-strategy, .p-roadmap { --fs-m: 25px; --lh-m: 31px; }

/* Type roles — 6 classes, 4 hierarchy tiers, weights 400/600 only. */
.t-display      { font-size: var(--fs-h); line-height: var(--lh-h); letter-spacing: var(--ls-h); font-weight: 600; color: var(--ink); }
.t-section      { font-size: var(--fs-m); line-height: var(--lh-m); letter-spacing: var(--ls-m); font-weight: 600; color: var(--ink); }
.t-body         { font-size: var(--fs-b); line-height: var(--lh-b); letter-spacing: var(--ls-b); font-weight: 400; color: var(--ink); }
.t-body-strong  { font-size: var(--fs-b); line-height: var(--lh-b); letter-spacing: var(--ls-b); font-weight: 600; color: var(--ink); }
.t-label        { font-size: var(--fs-s); line-height: var(--lh-s); letter-spacing: var(--ls-s); font-weight: 400; color: var(--ink-2); }
.t-label-strong { font-size: var(--fs-s); line-height: var(--lh-s); letter-spacing: var(--ls-s); font-weight: 600; color: var(--ink); }
.t-muted { color: var(--ink-2); }   /* the ONE ink override, for a --fs-b role. Never on --s2. */
.balance { text-wrap: balance; }
.pretty  { text-wrap: pretty; }

/* Card — the one grey shell. Box size, padding and layout belong to the surface. */
.card { background: var(--s1); border-radius: var(--r); corner-shape: squircle; }

/* Placeholder — the one image/media shell. Same shape, one tone darker. */
.ph   { background: var(--s2); border-radius: var(--r); corner-shape: squircle; }

/* Voice — the one standing affordance on an app screen. Square-with-squircle so
   it reads as the same family as a card, inverted so it never reads as content.
   The surface sets `bottom`: what it clears differs per screen. */
.fab { position: fixed; right: var(--sp-3); z-index: 20;
       width: 56px; height: 56px; display: grid; place-items: center;
       appearance: none; border: 0; cursor: pointer;
       background: var(--ink); color: var(--bg);
       border-radius: var(--r); corner-shape: squircle; }

/* Tab bar — the app's one standing nav. Three columns: a labelled tab, the voice
   control, a labelled tab. Voice sits IN the bar rather than floating over the
   content, so the bar is the only thing pinned to the bottom of a screen.
   Inverted by default; inside .inverted it flips with everything else. */
/* Icons only — no labels. The 80px side padding is Figma's 88 scaled, and it is
   what does the spacing: with space-between it puts the three marks on centres
   92 / 195 / 298, against the node's 90.7 / 195 / 299.3. Three equal columns
   would bunch them at 65 / 195 / 325 instead, so the padding is load-bearing.
   Icon sizes are set here, not on each <svg>, so the three screens carrying this
   bar cannot drift apart: 18 for the two tabs and 21 for voice, which is 0.75x the
   24/28 they were drawn at. The tap targets do NOT shrink with them — see the
   ::after overlay below, which holds 44px without touching the layout. */
.tabbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 10;
          height: var(--tabbar); padding: 0 80px;
          display: flex; align-items: center; justify-content: space-between;
          background: var(--ink); color: var(--bg); }
/* :not(.voice) — voice is the one column that is never the "current page" and so
   must never be dimmed. Without it the centre control reads as permanently off. */
.tabbar a:not(.voice) { position: relative; display: grid; place-items: center;
            color: inherit; text-decoration: none; opacity: 0.6; }
/* Beats the inline width/height on the <svg>. */
.tabbar a:not(.voice) svg { width: 18px; height: 18px; }
.tabbar .voice svg        { width: 21px; height: 21px; }
/* The target is a centred overlay rather than a minimum size on the box: a wider
   box would push the marks inward off the centres the node gives them, since the
   row is spaced by justify-content. This grows the hit area without moving a pixel. */
.tabbar a::after, .tabbar .voice::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
.tabbar a[aria-current="page"] { opacity: 1; }
.tabbar svg { display: block; }
/* Backgrounded. When the app is showing behind a live activity, its bar steps
   down to the page ground and its marks go to ink — the black dock below it is
   the foreground now, and two black bars stacked would read as one. It is a
   state of the same bar, not a second bar: only the two colours change. */
.tabbar--light { background: var(--bg); color: var(--ink); }
/* The voice control is the bar's centre column: same height as the tabs beside it,
   no label, never dimmed — it is the one control that is always available. */
/* Voice dims with the rest when it is not the live one, and lights up while its
   sheet is raised — the bar marks where you ARE, and the sheet is a place to be. */
.tabbar .voice { position: relative; display: grid; place-items: center;
                 appearance: none; border: 0; background: none; padding: 0;
                 color: inherit; text-decoration: none; cursor: pointer;
                 opacity: 0.6; }
.tabbar .voice[aria-expanded="true"] { opacity: 1; }

/* Voice sheet — the Sage prompt raised over whatever screen you were on, not a
   page you navigate to. It stops at the tab bar and covers nothing above it, so
   the screen behind stays readable: this is a mode you speak into. z-index sits
   UNDER the bar so it slides out from behind it rather than across it.
   .inverted supplies the ground and the ink, so this declares no colour.
   The 53px gap is Figma's 59 on the vertical scale; no space token is within
   4px of it, so the measurement stands rather than being snapped. */
.voicesheet {
  position: fixed; left: 0; right: 0; bottom: var(--tabbar); z-index: 9;
  height: 219px;
  /* Only the top corners are ever seen — it rises off the bottom edge and its
     bottom is always behind the bar. Rounding all four would put a curve where
     two opaque surfaces meet. */
  border-radius: var(--r) var(--r) 0 0; corner-shape: squircle;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 53px; text-align: center;
  visibility: hidden; transform: translateY(100%);
  transition: transform 260ms var(--ease-settle), visibility 260ms;
}
.voicesheet[data-open="true"] { visibility: visible; transform: none; }
/* Listening — the waveform breathes. It is the one mark in the app that says the
   microphone is open, and a still waveform says the opposite, so wherever it
   appears live it moves. Bars breathe on one loop, each a beat behind the last,
   which reads as a wave passing through rather than bars pulsing together.
   scaleY on the compositor, from 0.4 rather than 0 — nothing appears from
   nothing. Applied to the <svg>, so it works on the sheet's six stroked lines
   and onboarding's seven filled bars alike. */
.listening > * {
  transform-box: fill-box; transform-origin: center;
  animation: voice-wave 1100ms var(--ease-in-out) infinite alternate;
}
.listening > :nth-child(2) { animation-delay:  90ms; }
.listening > :nth-child(3) { animation-delay: 180ms; }
.listening > :nth-child(4) { animation-delay: 270ms; }
.listening > :nth-child(5) { animation-delay: 360ms; }
.listening > :nth-child(6) { animation-delay: 450ms; }
.listening > :nth-child(7) { animation-delay: 540ms; }
@keyframes voice-wave { from { transform: scaleY(0.4); } to { transform: scaleY(1); } }

/* A sheet that is not raised is not listening, and nothing should animate
   off-screen. */
.voicesheet:not([data-open="true"]) .listening > * { animation: none; }

/* Reduced motion is gentler, not zero: the sheet still arrives, it just arrives
   without travelling, and the waveform holds still. */
@media (prefers-reduced-motion: reduce) {
  .voicesheet { transition: none; }
  .listening > * { animation: none; }
}
}

/* Metric — label over value, one component, every box size on every surface. */
.metric { background: var(--s1); border-radius: var(--r); corner-shape: squircle;
          padding: var(--sp-2); display: flex; flex-direction: column; justify-content: space-between; }

/* Rows — hairline between siblings only, never above the first or below the last. */
.rows > * + * { border-top: 1px solid var(--line); }

/* Bar material — translucent blur. Two fallbacks, both fully opaque. */
.blur { background: var(--bar);
        -webkit-backdrop-filter: blur(var(--bar-blur));
                backdrop-filter: blur(var(--bar-blur)); }
@supports not (backdrop-filter: blur(1px)) { .blur { background: var(--bg); } }
@media (prefers-reduced-transparency: reduce) {
  .blur { background: var(--bg); -webkit-backdrop-filter: none; backdrop-filter: none; }
}

/* Toast — one instance per surface, inverted, class-driven. */
.toast { position: fixed; left: 50%; bottom: var(--sp-4); z-index: 900;
         height: 44px; padding: 0 var(--sp-3); display: grid; place-items: center; white-space: nowrap;
         background: var(--ink); color: var(--bg); border-radius: var(--r); corner-shape: squircle;
         font-size: var(--fs-b); line-height: var(--lh-b); font-weight: 400;
         opacity: 0; transform: translate(-50%, 8px); transform-origin: bottom center; pointer-events: none;
         transition: opacity 160ms var(--ease-in), transform 160ms var(--ease-in); }
.toast.show { opacity: 1; transform: translate(-50%, 0);
              transition: opacity 200ms var(--ease-out), transform 200ms var(--ease-out); }

/* Press — every pressable element on both surfaces. */
.press        { transition: transform 120ms var(--ease-out); }
.press:active { transform: scale(0.97); }

/* Focus — never removed, never replaced. `a` is listed explicitly: a bare
   <a href> carries no tabindex, so it matched none of the others and fell back to
   the browser's own ring. Every card that links somewhere is one of these. */
a:focus-visible, button:focus-visible, [tabindex]:focus-visible, summary:focus-visible {
  outline: 2px solid var(--ink); outline-offset: 2px;
}

/* Scroll — no visible scrollbar on any surface. */
.noscrollbar { scrollbar-width: none; }
.noscrollbar::-webkit-scrollbar { display: none; }

@media (prefers-reduced-motion: reduce) {
  .press { transition: none; }
  .press:active { transform: none; opacity: 0.6; }
  .toast, .toast.show { transform: translate(-50%, 0); }
  .toast      { transition: opacity 160ms var(--ease-in); }
  .toast.show { transition: opacity 200ms var(--ease-out); }
  * { scroll-behavior: auto !important; }
}

/* ---- Web shared (promoted 2026-07-29: home.html + pdp.html both use these) ---- */

/* Page-to-page navigation crossfades instead of flashing; the nav is snapshotted
   as its own element so the logo and links hold still across loads. */
@view-transition { navigation: auto; }
.nav { view-transition-name: nav; }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}

.wrap { width: var(--content); margin: 0 auto; }
.nav { position: fixed; top: 0; left: 0; width: 100%; height: 72px; z-index: 900; }
.nav-inner { display: flex; align-items: center; justify-content: space-between; height: 100%; }
.nav-links { display: flex; gap: var(--sp-3); align-items: center; }
.nav-item { position: relative; font-size: var(--fs-s); line-height: var(--lh-s); letter-spacing: var(--ls-s); color: var(--ink-2); text-decoration: none; }
.nav-item.current { font-weight: 600; color: var(--ink); }
a.nav-item:hover { color: var(--ink); }
.btn {
  display: grid; place-items: center;
  background: var(--ink); color: var(--bg);
  border: none; border-radius: var(--r); corner-shape: squircle;
  /* Longhands, not the `font` shorthand: `inherit` is not a legal family there,
     so `font: 600 16px/21px inherit` was invalid and the parser dropped the whole
     declaration — every .btn on every surface fell back to the UA default 13.33px.
     Family is omitted on purpose; it inherits from body, which is what was meant. */
  font-size: var(--fs-b); line-height: var(--lh-b); font-weight: 600;
  cursor: pointer; text-decoration: none;
}
.btn:hover  { opacity: 0.88; }
.btn--full { width: 100%; height: 56px; }
.btn--bar  { height: 44px; padding: 0 var(--sp-3); }

.nav-logo { color: var(--ink); text-decoration: none; }
.nav-cta  { display: grid; place-items: center; height: 40px; padding: 0 var(--sp-2);
            border-radius: 999px; background: var(--ink); color: var(--bg);
            font-size: var(--fs-s); font-weight: 600; text-decoration: none; }
.nav-cta:hover { opacity: 0.88; }
