/* Fridgerator — marketing + policy site
   Crisp, trustworthy, practical. Hairline-first, meaning-only color, calm
   authority. System font stack so it reads like the native app. */

:root {
  /* Every ratio below is measured against BOTH --surface (#fff) and the
     --surface-2 wash (#f5f6f8), because most of these appear on both. */
  --ink:        #16181c;   /* primary text. 17.77 / 16.44 */
  --ink-2:      #5b6069;   /* secondary text. 6.32 / 5.85 */
  --ink-3:      #6b7078;   /* tertiary / captions. 4.98 / 4.61 */
  --surface:    #ffffff;
  --surface-2:  #f5f6f8;   /* section wash, true-neutral (not cream) */
  --hairline:   #d9dce1;   /* use this one on the --surface-2 wash */
  --hairline-2: #e8eaee;   /* white-background only; 1.11 on the wash */

  --action:     #2680e6;   /* the one accent. Fills only, never text */
  --action-ink: #1a63b8;   /* accent text on light. 5.96 / 5.52 */

  /* Status ramp. Meaning only — never decoration, and always paired with an
     icon and plain words, so it survives colour-blindness and greyscale. */
  --good:       #1c7a34;   /* fresh.    5.41 / 5.00 */
  --good-bg:    #e7f6ec;   /* tinted panel behind --good text: 4.84 */
  --warning:    #8a5d09;   /* expiring. 5.75 / 5.32 */
  --critical:   #b3332a;   /* expired.  6.13 / 5.67 */

  --radius:     18px;
  --radius-sm:  12px;
  --maxw:       1080px;

  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
          "Segoe UI", system-ui, sans-serif;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font);
  color: var(--ink);
  background: var(--surface);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: var(--action-ink); text-decoration: none; }
a:hover { text-decoration: underline; }

.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 24px; }

/* ---- Top bar ---------------------------------------------------------- */
.nav {
  position: sticky; top: 0; z-index: 10;
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid var(--hairline-2);
}
.nav .wrap { display: flex; align-items: center; justify-content: space-between; height: 56px; }
/* Every header/footer link is a standalone target, so each gets the full 44px
   of height rather than the 21-26px a bare text link renders at. Links inside
   a sentence are deliberately left alone — WCAG 2.5.8 exempts inline targets,
   and padding them would wreck the line rhythm of the paragraph. */
.brand { display: flex; align-items: center; gap: 10px; min-height: 44px; font-weight: 600; color: var(--ink); font-size: 17px; letter-spacing: -0.01em; }
.brand .mark {
  width: 26px; height: 26px; border-radius: 7px;
  background: var(--good); display: grid; place-items: center;
  color: #fff; font-size: 15px; font-weight: 700;
}
.nav-links { display: flex; gap: 22px; font-size: 15px; }
.nav-links a { display: flex; align-items: center; min-height: 44px; color: var(--ink-2); }
.nav-links a:hover { color: var(--ink); text-decoration: none; }

/* Mobile header navigation. The five desktop links are section anchors on a
   short linear page — a phone visitor reaches those by scrolling, which is
   what they do anyway. What they genuinely cannot reach without travelling
   4,900px to the footer is Support and Privacy, so those two come up into the
   header instead. Two real targets beat a hamburger replicating a menu nobody
   opens, and it needs no JavaScript, which this site does not have. */
.nav-utility { display: none; gap: 18px; font-size: 15px; }
.nav-utility a { display: flex; align-items: center; min-height: 44px; color: var(--ink-2); }
.nav-utility a:hover { color: var(--ink); text-decoration: none; }

/* ---- Hero ------------------------------------------------------------- */
.hero { padding: clamp(56px, 9vw, 104px) 0 clamp(40px, 6vw, 72px); }
.hero .wrap { display: grid; grid-template-columns: 1.05fr 0.95fr; gap: clamp(32px, 5vw, 72px); align-items: center; }
.eyebrow { color: var(--good); font-weight: 600; font-size: 15px; letter-spacing: -0.005em; margin: 0 0 14px; }
h1 {
  font-size: clamp(40px, 6.4vw, 68px);
  line-height: 1.02; letter-spacing: -0.035em; font-weight: 700;
  margin: 0 0 20px; text-wrap: balance;
}
.lede { font-size: clamp(18px, 2.1vw, 21px); color: var(--ink-2); margin: 0 0 30px; max-width: 34ch; text-wrap: pretty; }

.cta-row { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
/* A status chip, not a button. Nothing is downloadable yet, so this must read
   as information: hairline outline instead of a solid fill, default cursor,
   no hover. A filled black pill next to an Apple mark reads as "tap me", and
   the page has nothing to tap. */
.badge {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--hairline);
  padding: 11px 19px; border-radius: 13px;
  font-weight: 600; font-size: 16px;
  cursor: default;
}
.badge small { display: block; font-size: 11px; font-weight: 500; color: var(--ink-2); letter-spacing: .02em; }
/* Carries the price, so it is not tertiary text. */
.note { color: var(--ink-2); font-size: 14px; }

/* ---- Phone mock ------------------------------------------------------- */
.phone {
  justify-self: center;
  /* The hero centres its text below 820px; the app screen inside must not
     inherit that or the mock depicts a centre-aligned list that doesn't exist. */
  text-align: left;
  width: 340px; max-width: 100%;
  border-radius: 50px;
  background: #0b0b0d;
  padding: 13px;
  box-shadow: 0 1px 2px rgba(0,0,0,.14), 0 34px 68px -24px rgba(20,24,32,.42);
}
.screen {
  border-radius: 38px; overflow: hidden; background: var(--surface);
  border: 1px solid #22232a;
  /* Real-iPhone proportions (≈19.5:9). Content fills from the top; the
     remaining screen below reads as more list, capped by the home indicator. */
  aspect-ratio: 9 / 19.5; position: relative;
}
.home-ind { position: absolute; left: 50%; bottom: 9px; z-index: 2; transform: translateX(-50%); width: 120px; height: 5px; border-radius: 999px; background: rgba(20,24,32,.28); }
.statusbar { height: 40px; position: relative; }
.island { position: absolute; top: 11px; left: 50%; transform: translateX(-50%); width: 96px; height: 26px; border-radius: 999px; background: #0b0b0d; }
.appbar { padding: 14px 20px 6px; }
.appbar .gear { width: 17px; height: 17px; color: var(--action); display: block; margin-bottom: 8px; }
.appbar .t { font-size: 29px; font-weight: 700; letter-spacing: -0.02em; }
.appbar .sub { font-size: 13px; color: var(--ink-3); margin-top: 2px; }
.chips { display: flex; gap: 7px; padding: 11px 20px 7px; }
.chip { font-size: 12px; font-weight: 600; padding: 5px 11px; border-radius: 999px; border: 1px solid var(--hairline); color: var(--ink-2); white-space: nowrap; }
/* A real colour, not opacity — .6 alpha on --ink-2 lands at 3.0:1. */
.chip i { font-style: normal; color: var(--ink-3); margin-left: 2px; }
.chip.on { background: var(--ink); color: var(--surface); border-color: var(--ink); }
.chip.on i { color: rgba(255,255,255,.72); }

/* The row mirrors the app: a 3px status rail on the leading edge, the name and
   brand, a symbol + plain-words status, and a tabular day count. Status is
   triple-encoded (colour + icon + words), so the rail is a gauge rather than
   the decorative side-stripe the design system bans. */
.rows { padding: 3px 14px 0; }
.row { display: flex; align-items: center; gap: 11px; padding: 9px 6px; border-bottom: 1px solid var(--hairline-2); }
.row:last-child { border-bottom: 0; }
.rail { width: 3px; align-self: stretch; border-radius: 2px; flex: none; }
.rmain { flex: 1; min-width: 0; }
.row .name { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; }
.row .cat { font-size: 11.5px; color: var(--ink-3); margin-top: 1px; }
.stat { display: flex; align-items: center; gap: 4px; font-size: 11.5px; font-weight: 500; margin-top: 3px; }
.si { width: 11px; height: 11px; flex: none; }
.count { flex: none; width: 44px; text-align: center; }
.count b { display: block; font-size: 17px; font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums; }
.count i { font-style: normal; font-size: 9.5px; color: var(--ink-3); }
/* The add control the real list has; without it the mock depicts an app with
   no way to put anything in it. */
.fab {
  position: absolute; right: 15px; bottom: 24px; z-index: 2;
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--action); color: #fff;
  display: grid; place-items: center;
  font-size: 23px; font-weight: 300; line-height: 1; padding-bottom: 2px;
}
/* The list runs past the bottom of the frame on purpose — it reads as "more
   below" and removes the blank tail the old five-row mock had. This scrim
   fades the clipped row out so it never collides with the home indicator. */
.screen::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 58px;
  background: linear-gradient(to top, var(--surface) 38%, transparent);
  pointer-events: none;
}
.g  { color: var(--good); }      .g.rail  { background: var(--good); }
.w  { color: var(--warning); }   .w.rail  { background: var(--warning); }
.c  { color: var(--critical); }  .c.rail  { background: var(--critical); }

/* ---- Showcase gallery -------------------------------------------------- */
/* Real captures in a bezel — same device language as the hero mock, sized
   down. The image supplies its own status bar and island, so the frame here
   draws neither. */
.gallery { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(18px, 2.6vw, 30px); }
.gallery:focus-visible { outline: 2px solid var(--action); outline-offset: 14px; border-radius: 4px; }

.shot { margin: 0; }
.device {
  border-radius: 34px;
  background: #0b0b0d;
  padding: 8px;
  box-shadow: 0 1px 2px rgba(0,0,0,.14), 0 24px 46px -22px rgba(20,24,32,.44);
  transition: transform .4s cubic-bezier(.16,1,.3,1), box-shadow .4s cubic-bezier(.16,1,.3,1);
}
.device img {
  display: block; width: 100%; height: auto;
  border-radius: 27px; border: 1px solid #22232a;
}
/* Pointer-only. On touch, :hover latches after a tap and the lifted card
   stays lifted with no way to dismiss it. */
@media (hover: hover) and (pointer: fine) {
  .shot:hover .device { transform: translateY(-5px); box-shadow: 0 1px 2px rgba(0,0,0,.14), 0 34px 58px -22px rgba(20,24,32,.5); }
}
.shot figcaption {
  margin-top: 16px; font-size: 15.5px; font-weight: 600;
  letter-spacing: -0.01em; color: var(--ink); text-wrap: pretty;
}

/* The page's one authored moment: the devices settle as they scroll in.
   Scroll-driven, so it degrades to the plain static grid where unsupported. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) and (min-width: 901px) {
    .shot {
      animation: shot-settle both cubic-bezier(.16,1,.3,1);
      animation-timeline: view();
      animation-range: entry 8% cover 30%;
    }
    .shot:nth-child(2) { animation-range: entry 4% cover 32%; }
    .shot:nth-child(3) { animation-range: entry 0% cover 34%; }
    .shot:nth-child(4) { animation-range: entry -4% cover 36%; }
    @keyframes shot-settle {
      from { opacity: .5; transform: translateY(26px); }
      to   { opacity: 1;  transform: none; }
    }
  }
}

/* ---- Features --------------------------------------------------------- */
/* scroll-margin clears the 56px sticky header on anchor jumps. Section padding
   happens to exceed it today, so this is insurance against that changing. */
.section, .hero { scroll-margin-top: 68px; }
.section { padding: clamp(48px, 7vw, 88px) 0; }
.section.alt { background: var(--surface-2); border-top: 1px solid var(--hairline-2); border-bottom: 1px solid var(--hairline-2); }
.section h2 { font-size: clamp(28px, 3.6vw, 40px); letter-spacing: -0.03em; line-height: 1.08; margin: 0 0 14px; text-wrap: balance; }
.section .intro { color: var(--ink-2); font-size: clamp(17px, 1.9vw, 19px); max-width: 56ch; margin: 0 0 44px; }

.features { display: grid; grid-template-columns: repeat(2, 1fr); gap: 2px; background: var(--hairline-2); border: 1px solid var(--hairline-2); border-radius: var(--radius); overflow: hidden; }
.feature { background: var(--surface); padding: 30px 28px; }
/* On the wash, --hairline-2 is 1.11:1 and the grid stops reading as one
   grouped unit. Step to --hairline, which is the token for this background. */
.section.alt .feature { background: var(--surface-2); }
.section.alt .features { background: var(--hairline); border-color: var(--hairline); }
.feature .ic { width: 34px; height: 34px; margin-bottom: 16px; color: var(--ink); }
.feature h3 { font-size: 19px; letter-spacing: -0.015em; margin: 0 0 8px; }
.feature p { color: var(--ink-2); margin: 0; font-size: 15.5px; }

/* ---- Steps ------------------------------------------------------------ */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; }
.step .n { font-size: 14px; font-weight: 700; color: var(--good); font-variant-numeric: tabular-nums; margin-bottom: 10px; }
.step h3 { font-size: 18px; letter-spacing: -0.015em; margin: 0 0 6px; }
.step p { color: var(--ink-2); margin: 0; font-size: 15.5px; }

/* ---- FAQ / support ---------------------------------------------------- */
.faq { display: grid; gap: 2px; background: var(--hairline-2); border: 1px solid var(--hairline-2); border-radius: var(--radius); overflow: hidden; max-width: 760px; }
details { background: var(--surface); padding: 0; }
summary { cursor: pointer; list-style: none; padding: 20px 24px; font-weight: 600; font-size: 17px; letter-spacing: -0.01em; display: flex; justify-content: space-between; align-items: center; }
summary::-webkit-details-marker { display: none; }
summary::after { content: "+"; color: var(--ink-3); font-weight: 400; font-size: 22px; }
details[open] summary::after { content: "–"; }
details p { margin: 0; padding: 0 24px 22px; color: var(--ink-2); font-size: 15.5px; max-width: 62ch; }

/* ---- Legal / policy pages -------------------------------------------- */
.doc { padding: clamp(40px, 6vw, 72px) 0 96px; }
.doc .wrap { max-width: 760px; }
.doc h1 { font-size: clamp(30px, 4vw, 42px); margin-bottom: 6px; }
.doc .eff { color: var(--ink-3); font-size: 14px; margin: 0 0 32px; }
.doc h2 { font-size: 21px; letter-spacing: -0.02em; margin: 40px 0 10px; }
.doc p, .doc li { color: #2c3038; font-size: 16.5px; line-height: 1.62; }
.doc ul { padding-left: 22px; }
.doc li { margin: 6px 0; }
.doc .callout { background: var(--good-bg); border: 1px solid color-mix(in srgb, var(--good) 22%, transparent); border-radius: var(--radius-sm); padding: 16px 20px; color: #1c5a2f; font-size: 16px; }

/* ---- Footer ----------------------------------------------------------- */
.foot { border-top: 1px solid var(--hairline-2); padding: 32px 0 40px; color: var(--ink-3); font-size: 14px; }
.foot .wrap { display: flex; flex-wrap: wrap; gap: 4px 28px; align-items: center; justify-content: space-between; }
.foot a { color: var(--ink-2); }
.foot-links { display: flex; gap: 4px 22px; flex-wrap: wrap; }
.foot-links a { display: inline-flex; align-items: center; min-height: 44px; }

/* ---- Responsive ------------------------------------------------------- */
/* Below the 4-up breakpoint the gallery becomes a snapping rail that bleeds
   to both edges, so the row reads as scrollable instead of squeezed. */
@media (max-width: 900px) {
  .gallery {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: minmax(206px, 58vw);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    margin-inline: -24px;
    padding: 4px 24px 10px;
    scrollbar-width: thin;
  }
  .shot { scroll-snap-align: center; }
  .device { border-radius: 30px; padding: 7px; }
  .device img { border-radius: 24px; }
}

@media (max-width: 820px) {
  .hero .wrap { grid-template-columns: 1fr; text-align: center; }
  .lede { margin-left: auto; margin-right: auto; }
  .cta-row { justify-content: center; }
  /* Source order stands: what the app *is* comes before a picture of it, so
     the mock is shrunk to peek above the fold and pay off the first scroll
     rather than consume the whole first screen. `zoom` rather than a width
     override — the mock's internals are absolute px, so narrowing the frame
     alone wraps the item names and leaves the UI reading as zoomed-in; this
     scales frame, radii, type and shadow together (340 x 0.7 = 238px). Where
     `zoom` is unsupported it falls back to the full-size mock, which is now
     below the fold either way. */
  .phone { zoom: 0.7; }
  .features { grid-template-columns: 1fr; }
  .steps { grid-template-columns: 1fr; gap: 24px; }
  .nav-links { display: none; }
  .nav-utility { display: flex; }
}

/* 340px and below: hide the wordmark so the two utility links keep their full
   targets instead of being squeezed. Clipped rather than display:none, so the
   home link is still named "Fridgerator" for a screen reader instead of "✓". */
@media (max-width: 340px) {
  .brand .word {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  .nav-utility { gap: 12px; font-size: 14px; }
}

/* Landscape phone. The width (844pt) clears the 820px breakpoint, so the
   two-column hero applies while the viewport is shorter than the mock is
   tall — the page would open on a slab of bezel. Shrink the mock and tighten
   the vertical padding so the headline and lede own the first screen. */
@media (max-height: 520px) and (orientation: landscape) {
  .hero { padding: 40px 0 32px; }
  .phone { zoom: 0.55; }
  .section { padding: 44px 0; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}
