/* ==========================================================================
   Kairi marketing site — stylesheet

   The app's palette, laid out editorially. Every colour below is lifted from
   shared/src/commonMain/kotlin/com/kairi/app/ui/theme/Color.kt, so a surface
   here is the same colour as the surface it stands for in the app — the cream
   is the logo's own cream, the greens are the logo's and the brand's, and the
   dark is the plate the app icon sits on.

   The rules the whole sheet is held to, so nothing creeps back in:
     - The palette is the app's. No colour is invented for the website.
     - Forest is the primary button. It is not a heading, a rule or a link.
     - No pure black and no pure white.
     - Two weights, 400 and 500. No gradient text.
     - No drop shadows, no glass, no blur, no icon discs, no badges, no emoji.
     - Whitespace and a tinted card separate ideas. Nothing is outlined.
     - Motion is a 400ms/16px fade-up on scroll, and nothing else. Hover
       changes colour or an underline, never scale, lift, glow or rotation.
   ========================================================================== */

:root {
  /* Grounds. LogoCream is the cut of the wordmark and the page's paper; Linen
     is the app's own background, a half-step cooler, for the band that has to
     separate itself from the cream. Plate is the ground the launcher icon
     sits on and the one dark surface on the site. */
  --cream: #F9F1E6;
  --linen: #F8FAFA;
  --plate: #012620;
  --plate-ink: #F9F1E6;

  /* Card tints, all from Color.kt. A bento card is one of these and nothing
     else: no borders, no shadows, no gradients. */
  --sage: #D5EFEC;
  /* MascotGreenSurface: the pale green the app draws the Plus card's two
     corner shapes in. It is used for exactly that here too. */
  --plus-shape: #F0FAE4;
  --mint: #C0E0B4;
  --butter: #FFF3DE;
  --peach: #F7E9D2;

  /* Ink. LogoDeep for type, Slate for the second voice. Both the app's. */
  --ink: #02322C;
  --ink-soft: #5E6668;

  /* The hairline: ink at 12%, so it sits correctly on cream, on linen and on
     every card tint without a second token per ground. */
  --line: rgba(2, 50, 44, 0.12);
  --line-dark: rgba(249, 241, 230, 0.2);

  /* Forest is the primary button, and the accent for nothing else. Lime is the
     logo's bean, used once: the numerals on the plate card, where teal would
     disappear. */
  --forest: #006B64;
  --forest-press: #004D48;
  --lime: #D1E214;

  /* Type. Both from the reference the design was taken from: a grotesque with
     some warmth in it for headlines, and a geometric humanist for everything
     else. The serif that was here before was doing an impression of an
     editorial brand rather than being one. */
  --font-display: "Bricolage Grotesque", "Segoe UI", system-ui, sans-serif;
  --font-body: "DM Sans", "Segoe UI", system-ui, sans-serif;

  /* Spacing */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4.5rem;
  --space-9: 7rem;

  /* Sections breathe. 140px is the middle of the 120-160 band; a section that
     feels empty at this height is at the right height. */
  --section-y: 140px;

  /* Radius. One value for every card and image, one for pills. */
  --radius: 24px;
  --radius-sm: 12px;
  --radius-pill: 999px;

  --container-width: 1200px;
  --header-height: 72px;
}

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

html {
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 17px;
  font-weight: 400;
  line-height: 1.6;
  color: var(--ink);
  background: var(--cream);
  -webkit-font-smoothing: antialiased;
}

img {
  max-width: 100%;
  display: block;
  /* Every img carries width/height attributes so the browser can reserve space
     before the file arrives. Without this, the height attribute stays in force
     when CSS overrides only the width, and the image renders stretched. */
  height: auto;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.1;
  /* Tight, but less so than the serif this replaced: a grotesque already sets
     closer, and at -0.02em the big headlines started to touch. */
  letter-spacing: -0.015em;
  margin: 0 0 var(--space-4);
}

p {
  margin: 0 0 var(--space-4);
}

/* Links in running text are ink with a hairline under them. The accent is
   spoken for; an accent-coloured link would make it two things at once. */
a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  text-decoration-color: var(--line);
  transition: text-decoration-color 0.15s ease, color 0.15s ease;
}

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

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.article-body ul,
.legal-shell ul {
  list-style: disc;
}

button {
  font-family: inherit;
}

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

.skip-link {
  position: absolute;
  left: -999px;
  top: var(--space-2);
  z-index: 200;
  background: var(--forest);
  color: var(--cream);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  text-decoration: none;
}

.skip-link:focus {
  left: var(--space-2);
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ---------- Layout ---------- */
.container {
  width: 100%;
  max-width: var(--container-width);
  margin: 0 auto;
  padding: 0 var(--space-6);
}

section {
  padding: var(--section-y) 0;
}

/* The grounds. The class names are the generators' and predate the palette;
   what they resolve to is the app's cream, the app's linen and the app's sage. */
.bg-white {
  background: var(--cream);
}

.bg-linen {
  background: var(--linen);
}

.bg-sage {
  background: var(--sage);
}

/* A section head is left-aligned and narrow. `.center` still centres it,
   because the blog and the category hubs ask for that. */
.section-head {
  max-width: 34rem;
  margin: 0 0 var(--space-8);
}

.section-head.center {
  margin-inline: auto;
  text-align: center;
}

/* Small caps label. Ink-soft, never the accent. */
.eyebrow {
  display: block;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: var(--space-5);
}

.section-title {
  font-size: clamp(2.25rem, 1.4rem + 3vw, 3.5rem);
  margin-bottom: var(--space-4);
  text-wrap: balance;
}

.section-subtitle {
  color: var(--ink-soft);
  font-size: 1.0625rem;
  margin-bottom: 0;
  max-width: 34em;
}

.section-head.center .section-subtitle {
  margin-inline: auto;
}

/* Kept because older markup still carries it; it is now plain emphasis rather
   than a coloured, underlined highlight. */
.highlight {
  color: var(--ink);
}

/* ---------- Buttons and links ---------- */
/* Exactly two. A solid accent pill with dark text, and a plain text link with
   an arrow. Every page uses these two and no others. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 1rem;
  line-height: 1;
  padding: var(--space-4) var(--space-6);
  border: 0;
  border-radius: var(--radius-pill);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  min-height: 52px;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.btn-primary {
  background: var(--forest);
  color: var(--cream);
}

.btn-primary:hover {
  background: var(--forest-press);
  color: var(--cream);
}

/* The secondary action everywhere: text, an arrow, a hairline that darkens on
   hover. Not a button, because it is not one. */
.btn-secondary,
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 52px;
  padding: 0;
  background: none;
  border: 0;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 1rem;
  color: var(--ink);
  cursor: pointer;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.3em;
  text-decoration-color: var(--line);
  transition: text-decoration-color 0.15s ease;
}

.btn-secondary::after,
.link-arrow::after {
  content: "\2192";
  text-decoration: none;
  /* The arrow is punctuation on the end of a sentence, not a moving part. */
  font-size: 1.05em;
  line-height: 1;
}

.btn-secondary:hover,
.link-arrow:hover {
  text-decoration-color: var(--ink);
}

.btn-sm {
  min-height: 44px;
  padding: var(--space-3) var(--space-5);
  font-size: 0.9375rem;
}

.btn-block {
  width: 100%;
}

/* ---------- Store links ----------
   The stores' own badges, unaltered. Nothing here recolours, outlines, rounds
   or re-draws them — the only thing this sheet decides is how tall they are,
   which is the one dimension both Google and Apple leave to you.

   They share an aspect ratio to within a thousandth, so one height lines the
   pair up with no per-badge correction. 48px clears both stores' 40px minimum
   with room to spare and reads as a real control rather than a footnote. */
.store-badges {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  margin: var(--space-6) 0;
}

.store-badge {
  display: inline-flex;
  align-items: center;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  text-decoration: none;
  -webkit-appearance: none;
  appearance: none;
  /* The artwork carries its own rounded corner, so the focus ring has to
     follow it rather than boxing the badge in a rectangle. */
  border-radius: 8px;
}

.store-badge picture,
.store-badge img {
  display: block;
  height: 48px;
  width: auto;
}

/* The one hover the badges get: a touch of transparency. Anything more would
   be altering artwork neither store allows you to alter. */
.store-badge:hover {
  opacity: 0.88;
}

/* ---------- Header ----------
   Thin, sticky, solid paper, one hairline. No blur: a translucent bar over a
   photograph is the glass effect this redesign removed everywhere else. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--cream);
  border-bottom: 1px solid var(--line);
}

.site-header .container {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  height: var(--header-height);
  gap: var(--space-4);
}

.brand {
  display: flex;
  align-items: center;
  justify-self: start;
  text-decoration: none;
}

.brand-wordmark {
  /* Half the bar's height. At 26px it was the quietest thing in a row that
     also held a filled button, which is the wrong way round: the one element
     in a header that has to be unmissable is whose site this is. */
  height: 36px;
  width: auto;
  flex-shrink: 0;
}

.main-nav {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  justify-self: end;
  padding: var(--space-2) var(--space-6);
  border-radius: var(--radius-pill);
  background: var(--linen);
}

.main-nav a {
  font-weight: 400;
  font-size: 0.9375rem;
  color: var(--ink-soft);
  text-decoration: none;
}

.main-nav a:hover {
  color: var(--ink);
}

.header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  justify-self: end;
}

.header-store {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

/* One CTA in the bar, and it is a button rather than a store badge — see
   header_store_link() in build.py for why the badge came back out of here.
   The App Store link was the second CTA, and two in a thin header is one more
   than the design allows; it still sits in the hero, the closing block, the
   footer and the mobile drawer, so the waitlist is never more than one screen
   away. */
.btn-store {
  min-height: 40px;
  padding: 0 var(--space-5);
  font-size: 0.9375rem;
}

/* EN / DA. A plain text pair with the current one in ink and the other under a
   hairline — the sage chip it used to sit in was the last tinted surface in
   the bar. */
.lang-switch {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
}

.lang-switch a,
.lang-switch span {
  line-height: 1;
  color: var(--ink-soft);
  text-decoration: none;
}

.lang-switch a:hover {
  color: var(--ink);
}

.lang-switch .is-current {
  color: var(--ink);
}

.lang-dropdown {
  position: relative;
}

.lang-dropdown summary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.9375rem;
  color: var(--ink-soft);
  line-height: 1;
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.lang-dropdown summary::-webkit-details-marker {
  display: none;
}

.lang-dropdown summary:hover {
  color: var(--ink);
}

.lang-dropdown summary svg {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
}

.lang-menu {
  position: absolute;
  top: calc(100% + var(--space-3));
  right: 0;
  display: flex;
  flex-direction: column;
  min-width: 130px;
  padding: var(--space-3) var(--space-4);
  background: var(--cream);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  z-index: 20;
}

.lang-menu a {
  padding: var(--space-2) 0;
  font-size: 0.9375rem;
  color: var(--ink);
  text-decoration: none;
}

.lang-menu a:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* The drawer toggle. Two hairlines, no box around them. */
.nav-toggle {
  display: none;
  position: relative;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  color: var(--ink);
}

.nav-toggle svg {
  width: 22px;
  height: 22px;
}

/* ---------- Mobile drawer ----------
   A panel that comes in from the trailing edge over a scrim, not a section
   that pushes the page down. */
.mobile-nav {
  position: fixed;
  inset: 0;
  z-index: 150;
  display: none;
}

.mobile-nav.is-open {
  display: block;
}

.mobile-nav::before {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(1, 38, 32, 0.4);
}

.mobile-nav .container {
  position: absolute;
  inset-block: 0;
  inset-inline-end: 0;
  width: min(22rem, 86vw);
  height: 100%;
  max-width: none;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  padding: calc(var(--header-height) + var(--space-6)) var(--space-6) var(--space-7);
  background: var(--cream);
}

.mobile-nav > .container > a {
  padding: var(--space-4) 0;
  font-family: var(--font-display);
  font-size: 1.5rem;
  color: var(--ink);
  border-bottom: 1px solid var(--line);
  text-decoration: none;
}

.mobile-nav .store-badges {
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-4);
  margin: var(--space-7) 0 0;
}

.mobile-nav .lang-switch.is-mobile {
  margin-top: var(--space-6);
  gap: var(--space-4);
  font-size: 0.9375rem;
}

.mobile-nav .lang-switch.is-mobile a,
.mobile-nav .lang-switch.is-mobile span {
  padding: var(--space-2) 0;
}

/* ==========================================================================
   Landing page
   ========================================================================== */

/* ---------- Hero ----------
   One photograph the full width of the section, one headline, one sentence,
   two actions. Nothing else stands above the fold. */
.hero {
  position: relative;
  overflow: hidden;
  display: grid;
  align-items: end;
  min-height: min(88vh, 46rem);
  padding: var(--section-y) 0 var(--space-9);
  background: var(--plate);
  color: var(--plate-ink);
}

.hero-media {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.hero-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 68% 42%;
}

/* The scrim. Two passes, and both are legibility rather than decoration — this
   is the one place on the site a gradient is allowed, because white type on a
   photograph has to be readable on the photograph's worst pixel.

   The horizontal pass is shaped to the copy column, not to the frame: it holds
   its weight to 52% (where the text ends) and then falls off fast, instead of
   fading evenly across the whole width. That is what lets the picture stay a
   picture — her face sits at 62% across, where this pass is already down to
   about a third — while the type still measures. The vertical pass only stops
   the sky blowing out at the top and the frame ending abruptly at the bottom.

   Measured against the photograph's brightest pixel under each element, not
   its average: 6.1:1 under the headline, 6.3:1 under the sentence and 12:1
   under the App Store link, against thresholds of 3.0, 4.5 and 4.5. */
.hero-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg,
      rgba(1, 38, 32, 0.86) 0%,
      rgba(1, 38, 32, 0.82) 34%,
      rgba(1, 38, 32, 0.60) 52%,
      rgba(1, 38, 32, 0.16) 72%,
      rgba(1, 38, 32, 0) 92%),
    linear-gradient(180deg,
      rgba(1, 38, 32, 0.34) 0%,
      rgba(1, 38, 32, 0.08) 30%,
      rgba(1, 38, 32, 0.34) 68%,
      rgba(1, 38, 32, 0.56) 100%);
}

.hero .container {
  position: relative;
  z-index: 1;
}

.hero-copy {
  max-width: 34rem;
}

.hero-copy h1 {
  font-size: clamp(2.5rem, 1.2rem + 5.4vw, 6rem);
  line-height: 1.02;
  color: var(--plate-ink);
  text-wrap: balance;
  margin: 0 0 var(--space-5);
}

.hero-copy .lede {
  font-size: 1.125rem;
  line-height: 1.6;
  color: rgba(249, 241, 230, 0.86);
  max-width: 32em;
  margin: 0 0 var(--space-6);
}

.hero .store-badges {
  margin: 0;
}

/* Kept for the generators that still emit it; it is no longer used above the
   fold, where the rule is a headline, a sentence and two buttons. */
.hero-note {
  margin: var(--space-6) 0 0;
  font-size: 0.875rem;
  color: rgba(249, 241, 230, 0.6);
}

/* ---------- Feature rows ----------
   A claim beside the screen that makes it good, sides alternating down the
   page. No cards, no borders, no rules between them: the gap is what says
   "next idea", so it is larger than anything inside a row. */
.feature-list {
  display: grid;
  gap: var(--space-9);
}

.feature-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-8);
  align-items: center;
}

/* Source order is copy-first on every row, so a screen reader and a phone both
   get the claim before the picture of it; this is presentation only. */
.feature-row:nth-child(even) .feature-visual {
  order: -1;
}

.feature-copy {
  max-width: 28rem;
}

.feature-copy h3 {
  font-size: clamp(1.75rem, 1.3rem + 1.4vw, 2.25rem);
  margin: 0 0 var(--space-4);
}

.feature-copy p {
  margin: 0;
  font-size: 1.0625rem;
  color: var(--ink-soft);
}

.feature-visual {
  display: flex;
  justify-content: center;
}

/* ---------- Screens ----------
   A capture on a quiet ground with the page's one radius. The phone shell it
   used to sit in was a dark gradient under a 44px shadow, which is two of the
   things this design removed wearing one hat. */
.device {
  position: relative;
  width: 100%;
  max-width: 320px;
  margin-inline: auto;
  padding: var(--space-5);
  border-radius: var(--radius);
  background: var(--sage);
}

/* No forced ratio, and so no crop. The frame used to pin every capture to
   880:1770 and cover() the difference away, anchored to the top, on the
   reasoning that captures come back at different heights and a fixed ratio
   beats letter-boxing.

   What it actually did was throw away evidence. Each of these screens is the
   proof for the claim beside it, and the frame was cutting 3-6% off the foot
   of most of them, 17% off the Danish swaps screen - which is the one whose
   row promises you can see what each swap is worth - and 6% off BOTH SIDES of
   the recipe screen, so its interface ran off the edges.

   Rows are stacked, not laid out side by side, so nothing needs them to be the
   same height. Each capture keeps its own shape; the width and height
   attributes are the file's own, so the box is still reserved before it
   loads. */
.device picture,
.device img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-sm);
}

/* The one capture that is not a whole screen: a notification arrives over
   whatever you were doing, so it gets no frame at all. */
.banner {
  width: 100%;
  max-width: 400px;
  margin-inline: auto;
}

.banner img {
  width: 100%;
  height: auto;
}

/* ---------- Four ways in ----------
   A bento of tinted cards, each carrying one of the app's own illustrations.
   This block has now been three things: four stroked icons in four sage discs,
   then one stock photograph with four lines of text beside it, and now the
   drawings the product already owns. The first said nothing, the second said
   it in the voice of every health site on the internet, and this one is the
   app's hand.

   A card is a tint and a radius. No border, no shadow, no gradient — the tints
   are what separate them from the cream, which is why they can sit edge to
   edge with nothing drawn between. */
.scan-block {
  margin-bottom: var(--space-9);
}

.bento {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-5);
}

.bento-card {
  position: relative;
  display: flex;
  flex-direction: column;
  /* Shorter than the lead card's, because a title with no sentence under it
     needs less room than one with. */
  min-height: 16rem;
  padding: var(--space-6);
  border-radius: var(--radius);
  background: var(--sage);
  overflow: hidden;
}

/* The lead card states the idea and takes two tracks; the four beside and
   under it are the four ways in. */
.bento-card.is-lead {
  grid-column: span 2;
  background: var(--linen);
  justify-content: center;
}

.bento-card.is-sage { background: var(--sage); }
.bento-card.is-mint { background: var(--mint); }
.bento-card.is-butter { background: var(--butter); }
.bento-card.is-peach { background: var(--peach); }

/* The four cards carry a title and nothing else, so it takes the size the
   title and its sentence used to share between them - but capped low enough
   that the longest of them ("Photograph the plate", "Fotografer menukortet")
   still sets on one line in a third of the bento.

   The bottom margin is not decoration. The drawing under it is pushed down by
   an auto margin, which goes to zero the moment a title wraps, and the two
   were touching. This is the floor under that gap, so the card survives a
   longer word or a narrower column in either language. */
.bento-card h3 {
  position: relative;
  z-index: 1;
  font-size: clamp(1.25rem, 1.05rem + 0.6vw, 1.5rem);
  margin: 0 0 var(--space-5);
}

.bento-card.is-lead h3 {
  font-size: clamp(1.75rem, 1.3rem + 1.4vw, 2.25rem);
  margin-bottom: var(--space-3);
}

.bento-card p {
  position: relative;
  z-index: 1;
  margin: 0;
  font-size: 0.9375rem;
  color: var(--ink-soft);
  max-width: 24em;
}

.bento-card.is-lead p {
  font-size: 1.0625rem;
}

/* The drawing sits in the card's bottom corner and is allowed to run off two
   of its edges: a picture that clears the card's padding on every side reads
   as a sticker placed on it rather than as part of it. */
.bento-art {
  position: relative;
  z-index: 0;
  margin: auto calc(var(--space-6) * -1) calc(var(--space-6) * -1) auto;
  width: 70%;
  max-width: 240px;
}

.bento-art img {
  width: 100%;
  height: auto;
}

.bento-card.is-lead .bento-art {
  position: absolute;
  inset-block-end: calc(var(--space-6) * -1);
  inset-inline-end: calc(var(--space-6) * -1);
  width: 42%;
  max-width: 260px;
  margin: 0;
}

/* ---------- Vision ----------
   The app's Plus card, on the website. Not "inspired by": the ground, the
   hairline and the two corner shapes are PlusCardShell and PlusCardBackdrop
   from shared/.../ui/plus/PlusUnlockCard.kt, down to the offsets and sizes the
   Canvas draws the ovals at - -10%/-16% at 24x34, and 84%/78% at 28x40.

   This block has been four things. Three numerals that said nothing; three
   named conditions that read like a spec sheet; then a statement alone on the
   dark plate, which is a quote graphic, and a quote graphic is what every
   other brand's vision block already is. The answer was not another layout.
   It was to stop inventing a box and use the one the product already has.

   Light, not dark, for the reason PlusCardShell's own docstring gives: the
   card used to be near-black and "made every inline Plus card the one dark
   slab on a light page". The app made that call; the site follows it.

   The app's ovals drift on a 6.5s loop. These do not. One fade-up on scroll is
   the whole of this site's motion, and a shape that breathes on its own would
   be the second thing. */
/* No padding of its own, either side. The section above it ends with a full
   --section-y of its own, and the closing block below opens with one, so the
   card gets an equal measure of cream top and bottom without adding any.

   It had --section-y underneath as well, which put 140px above the card and
   280px below it. Two different gaps around the same object is the kind of
   thing that reads as wrong before anyone can say why. */
.vision-band {
  padding: 0;
}

.vision-card {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--linen);
  border: 1px solid var(--sage);
  padding: var(--space-9) var(--space-8);
  color: var(--ink);
}

.vision-card::before,
.vision-card::after {
  content: "";
  position: absolute;
  z-index: 0;
  border-radius: 50%;
  background: var(--plus-shape);
}

.vision-card::before {
  left: -10%;
  top: -16%;
  width: 24%;
  height: 34%;
}

.vision-card::after {
  left: 84%;
  top: 78%;
  width: 28%;
  height: 40%;
}

/* Centred, and the card is symmetrical about its vertical axis: equal padding
   top and bottom, the heading and the sentence both on the centre line, and
   the two corner shapes opposite each other so they balance across the
   diagonal. Ranged left it was a short block of type in the left third of a
   1000px card with nothing in the other two thirds - not restraint, just an
   unfinished-looking box. */
.vision-copy {
  position: relative;
  z-index: 1;
  max-width: 44rem;
  margin-inline: auto;
  text-align: center;
}

/* A heading, not the 12px letterspaced caption it used to be. The paywall
   card this box is borrowed from leads with a heading too ("Las op for
   Kairi+"), and a label in small capitals is not a heading - it is the thing
   templates put above one. */
.vision-title {
  font-size: clamp(2rem, 1.4rem + 2.2vw, 3rem);
  color: var(--ink);
  margin: 0 0 var(--space-5);
}

/* The body under it, the way the paywall card sets its own line under its
   heading - but in ink rather than slate, because this sentence is the
   substance of the block and not a subtitle to it. */
.vision-statement {
  font-family: var(--font-body);
  font-size: clamp(1.125rem, 1rem + 0.5vw, 1.4375rem);
  line-height: 1.55;
  color: var(--ink);
  /* Short enough that the eye returns without hunting, and centred in the
     card like everything else in it. */
  max-width: 28em;
  margin: 0 auto;
}

/* ---------- Closing block ----------
   Image left, the offer right, one full-width button and one true sentence
   under it. */
.cta-wrap {
  padding: var(--section-y) 0;
}

.final-cta {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-8);
  align-items: center;
}

.final-cta-media img {
  width: 100%;
  border-radius: var(--radius);
  aspect-ratio: 4 / 5;
  object-fit: cover;
  background: var(--sage);
}

.final-cta h2 {
  font-size: clamp(2.25rem, 1.4rem + 3vw, 3.5rem);
  margin: 0 0 var(--space-4);
  text-wrap: balance;
}

.final-cta p {
  color: var(--ink-soft);
  margin: 0 0 var(--space-6);
  max-width: 30em;
}

.final-cta .store-badges {
  margin: 0 0 var(--space-5);
}

/* .product-trust is gone from the markup; .trust-microcopy survives because
   older blocks still carry it. */
.trust-microcopy {
  margin: 0;
  font-size: 0.9375rem;
  color: var(--ink-soft);
  max-width: 30em;
}

/* ---------- FAQ ----------
   The list on the left, a photograph on the right. The list caps at 44rem, so
   on a 1200px container it was leaving the whole right half of the section
   empty — the one place on the page where whitespace read as something
   missing rather than as room to breathe.

   The picture is sticky: the list is eight accordions tall and grows as they
   open, and a photograph that scrolls away after the second question leaves
   the same empty column it was put there to fill. */
.faq-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.56fr);
  gap: var(--space-8);
  align-items: start;
}

.faq-media {
  position: sticky;
  top: calc(var(--header-height) + var(--space-6));
}

/* A landscape photograph in a portrait frame is a crop decision, not a
   default. Centred, this one put a jug in the corner and cut the bowl in half
   at the right edge; anchored right it holds the whole bowl. Check the crop,
   not the photograph, whenever this changes. */
.faq-media img {
  width: 100%;
  border-radius: var(--radius);
  aspect-ratio: 3 / 4;
  object-fit: cover;
  object-position: right center;
  background: var(--sage);
}

/* Plain accordions on thin dividers. The marker is a typographic plus and
   minus set in the body face, not an icon. */
.faq-list {
  border-top: 1px solid var(--line);
}

.faq-item {
  border-bottom: 1px solid var(--line);
}

.faq-item summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-5);
  padding: var(--space-5) 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.375rem;
  letter-spacing: -0.01em;
  line-height: 1.3;
}

.faq-item summary::-webkit-details-marker {
  display: none;
}

.faq-item summary::after {
  content: "+";
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 1.25rem;
  line-height: 1;
  color: var(--ink-soft);
  flex-shrink: 0;
}

.faq-item[open] summary::after {
  content: "\2212";
}

.faq-answer {
  padding: 0 0 var(--space-6);
  max-width: 38rem;
  color: var(--ink-soft);
}

.faq-answer p:last-child {
  margin-bottom: 0;
}

/* ---------- Notes and disclaimers ----------
   Small print under one hairline. This was a butter-coloured panel with a
   border and a warning icon in it, on three different pages.

   One rule above and none below, and it is set smaller than the body it
   follows. Two rules made it a third block in a stack of blocks that all
   looked alike; one rule and a size drop make it read as a footnote to the
   article, which is what it is. */
.disclaimer-note,
.article-disclaimer {
  display: block;
  max-width: 44rem;
  margin-top: var(--space-7);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--ink-soft);
}

.disclaimer-note svg,
.article-disclaimer svg {
  display: none;
}

.disclaimer-note p {
  margin: 0;
}

.article-disclaimer {
  margin: var(--space-7) 0 var(--space-9);
}

/* ---------- Footer ----------
   Three link columns, one brand line, the copyright, and the wordmark set
   large enough to run off the bottom edge. */
.site-footer {
  position: relative;
  overflow: hidden;
  background: var(--plate);
  color: var(--plate-ink);
  padding: var(--space-8) 0 var(--space-6);
}

.footer-top {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: var(--space-7);
  padding-bottom: var(--space-7);
}

.footer-brand .brand {
  margin-bottom: var(--space-5);
}

.footer-brand .brand-wordmark {
  height: 40px;
}

.footer-brand .brand-wordmark {
  /* The lockup is drawn for paper. One filter puts it on the dark without a
     second file to keep in step with the first. */
  filter: brightness(0) invert(1);
  opacity: 0.9;
}

.footer-brand p {
  color: rgba(249, 241, 230, 0.7);
  font-size: 0.9375rem;
  max-width: 26em;
}

.footer-col h4 {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(249, 241, 230, 0.55);
  margin-bottom: var(--space-4);
}

.footer-col ul {
  display: grid;
  gap: var(--space-3);
}

.footer-col a,
.footer-store-links a,
.footer-store-links button {
  color: var(--plate-ink);
  font-size: 0.9375rem;
  text-decoration: none;
}

.footer-col a:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.footer-col a.is-subtle {
  color: rgba(249, 241, 230, 0.7);
}

.footer-store-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  margin-top: var(--space-5);
}

.footer-store-links picture,
.footer-store-links img {
  height: 42px;
}

.footer-bottom {
  display: flex;
  justify-content: flex-start;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-5);
  padding-top: var(--space-5);
  border-top: 1px solid var(--line-dark);
  color: rgba(249, 241, 230, 0.55);
  font-size: 0.8125rem;
}

.footer-company {
  margin-right: auto;
}

/* The Danish guide signup. Kept, because it is a live capture that feeds the
   guide list, but it is no longer a boxed newsletter card in the link
   columns: it is a line of text and a field above the columns. */
.footer-signup {
  grid-column: 1 / -1;
  order: -1;
  padding-bottom: var(--space-7);
  margin-bottom: var(--space-6);
  border-bottom: 1px solid var(--line-dark);
}

.footer-signup h4 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.5rem;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--plate-ink);
  margin-bottom: var(--space-3);
}

.footer-signup p {
  color: rgba(249, 241, 230, 0.7);
  font-size: 0.9375rem;
  max-width: 46ch;
  margin: 0 0 var(--space-5);
}

.footer-signup .email-cta-form {
  margin: 0;
  max-width: 28rem;
}

.footer-signup .email-cta-input {
  background: transparent;
  border-color: var(--line-dark);
  color: var(--plate-ink);
}

.footer-signup .email-cta-input::placeholder {
  color: rgba(249, 241, 230, 0.5);
}

.footer-signup .email-cta-status:empty {
  display: none;
}

/* Small print on the plate takes the cream at the weight the footer's other
   quiet text does; the ink-soft it inherits is for the light pages. */
.footer-signup .email-cta-disclaimer {
  color: rgba(249, 241, 230, 0.55);
}

/* ==========================================================================
   Blog
   ========================================================================== */

.blog-hero {
  padding: var(--space-9) 0 var(--space-8);
  background: var(--cream);
}

.blog-hero .section-title {
  max-width: 18em;
}

.blog-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-8) var(--space-6);
}

/* An entry, not a card. No panel, no border, no shadow, no lift: the picture,
   a small label, the title in the display face and the meta under a hairline.
   The grid reads as a contact sheet, which is what a blog index is. */
.article-card {
  display: flex;
  flex-direction: column;
  background: none;
  border: 0;
  border-radius: 0;
  padding: 0;
  height: 100%;
}

.article-thumb {
  display: block;
  margin: 0 0 var(--space-5);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--sage);
  aspect-ratio: 4 / 3;
}

.article-thumb img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.article-thumb.is-photo img {
  object-fit: cover;
}

.article-card .article-category,
a.article-category {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: var(--space-3);
  text-decoration: none;
}

a.article-category:hover {
  color: var(--ink);
}

.article-card h3 {
  font-size: 1.375rem;
  line-height: 1.2;
  margin-bottom: var(--space-3);
}

.article-card h3 a {
  color: var(--ink);
  text-decoration: none;
}

.article-card h3 a:hover {
  text-decoration: underline;
  text-underline-offset: 0.16em;
}

.article-card p {
  color: var(--ink-soft);
  font-size: 0.9375rem;
  flex: 1;
  margin-bottom: var(--space-4);
}

.article-meta {
  display: flex;
  gap: var(--space-4);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  margin-top: auto;
  padding-top: var(--space-3);
  border-top: 1px solid var(--line);
}

.article-card.is-soon {
  opacity: 0.55;
}

.category-count {
  color: var(--ink-soft);
  font-size: 0.9375rem;
  margin-top: var(--space-4);
}

/* ---------- Article page ---------- */
.article-shell {
  padding: var(--space-8) 0 var(--space-9);
}

.article-shell .container {
  max-width: 1080px;
}

.article-grid {
  display: grid;
  grid-template-columns: 1fr 260px;
  gap: var(--space-8);
  align-items: start;
}

.article-header {
  margin-bottom: var(--space-7);
}

.article-header .article-category {
  display: block;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: var(--space-4);
}

.article-header h1 {
  font-size: clamp(2.25rem, 1.5rem + 2.4vw, 3.25rem);
}

.article-byline {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--ink-soft);
  font-size: 0.9375rem;
  margin-top: var(--space-5);
}

.byline-editorial-link {
  display: block;
  font-size: 0.8125rem;
  color: var(--ink-soft);
  margin-top: 2px;
}

.article-body {
  font-size: 1.0625rem;
  max-width: 38rem;
}

.article-body h2 {
  font-size: 1.75rem;
  margin-top: var(--space-8);
}

.article-body h3 {
  font-size: 1.25rem;
  margin-top: var(--space-6);
}

.article-body ul,
.article-body ol {
  margin: 0 0 var(--space-4);
  padding-left: 1.3rem;
}

.article-body li {
  margin-bottom: var(--space-2);
}

.article-image {
  margin: var(--space-7) 0;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--sage);
}

.article-image img {
  width: 100%;
  height: auto;
}

.article-image figcaption {
  font-size: 0.8125rem;
  color: var(--ink-soft);
  padding: var(--space-4) var(--space-5);
}

.article-image.is-photo {
  background: none;
}

.photo-credit {
  font-size: 0.75rem;
  color: var(--ink-soft);
  margin: var(--space-3) 0 0;
}

/* The two blocks that close an article, and the reason this page needed
   fixing. Both used to be hairline bands: a rule, a heading, a paragraph, a
   rule. So did the disclaimer above them. Three blocks in a row, same cream,
   same rules, same left edge, same type — the foot of every article was one
   undifferentiated stretch and nothing said where the article stopped and the
   offers started.

   They are cards now, in the language the landing page already uses, and they
   are deliberately two different cards: the app pitch is the plate, the guide
   signup is butter. One is "here is the product", the other is "here is a
   thing to read", and a reader should be able to tell them apart at a glance
   without reading either. */
.article-cta,
.article-email-cta {
  margin: var(--space-8) 0;
  padding: var(--space-7);
  border: 0;
  border-radius: var(--radius);
}

/* The app block: the mark on the left, the pitch on the right. This is the
   one card on the site that is straightforwardly an advert for the app, and an
   advert for an app leads with the icon you are about to go looking for. */
.article-cta {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-6);
  align-items: start;
  background: var(--plate);
  color: var(--plate-ink);
}

.article-cta-mark {
  width: 72px;
  height: auto;
  flex-shrink: 0;
  /* Optical, not geometric: align-items:start lines the mark up with the top
     of the heading's line box, which sits above the letters themselves. */
  margin-top: 4px;
}

.article-email-cta {
  background: var(--butter);
}

.article-cta h3,
.article-email-cta h3 {
  font-size: 1.75rem;
  margin-bottom: var(--space-3);
}

.article-cta h3 {
  color: var(--plate-ink);
}

.article-cta p,
.article-email-cta p {
  margin-bottom: var(--space-5);
  max-width: 34em;
}

.article-cta p {
  color: rgba(249, 241, 230, 0.78);
}

.article-email-cta p {
  color: var(--ink-soft);
}

.article-cta .store-badges {
  margin: 0;
}

/* On butter the field's hairline has to be the ink's, not the cream's. */
.article-email-cta .email-cta-input {
  border-bottom-color: rgba(2, 50, 44, 0.25);
}

/* ---------- Guide signup form ---------- */
.email-cta-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  max-width: 34rem;
  margin: 0;
}

.email-cta-input {
  flex: 1;
  min-width: 0;
  font: inherit;
  font-size: 1rem;
  padding: var(--space-3) 0;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  color: var(--ink);
}

.email-cta-input:focus {
  outline: none;
  border-bottom-color: var(--ink);
}

.email-cta-button {
  padding: var(--space-3) var(--space-6);
  min-height: 48px;
  background: var(--forest);
  color: var(--cream);
  border: 0;
  border-radius: var(--radius-pill);
  font-family: inherit;
  font-size: 1rem;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.15s ease;
}

.email-cta-button:hover {
  background: var(--forest-press);
}

.email-cta-disclaimer {
  font-size: 0.8125rem;
  color: var(--ink-soft);
  margin: var(--space-4) 0 0;
}

.email-cta-hp {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.email-cta-status {
  flex-basis: 100%;
  font-size: 0.9375rem;
  margin: var(--space-2) 0 0;
  min-height: 1.2em;
}

.email-cta-status.is-ok {
  color: var(--ink);
}

.email-cta-status.is-error {
  color: #8C3A3A;
}

/* ---------- Article sidebar ----------
   Two tinted cards rather than two hairline-topped lists. On cream, beside a
   cream article column, the lists read as more article: same ground, same
   left edge, same type. A tint is what says "this is the rail". */
.article-sidebar {
  position: sticky;
  top: calc(var(--header-height) + var(--space-5));
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.toc-box,
.related-box {
  border: 0;
  border-radius: var(--radius);
  padding: var(--space-5);
}

.toc-box {
  background: var(--linen);
}

.related-box {
  background: var(--sage);
}

.toc-box h4,
.related-box h4 {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: var(--space-4);
}

.toc-box ol {
  list-style: none;
  padding: 0;
  display: grid;
  gap: var(--space-3);
}

.toc-box li {
  font-size: 0.9375rem;
}

.toc-box a,
.related-box a {
  color: var(--ink);
  text-decoration: none;
}

.toc-box a:hover,
.related-box a:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.related-box ul {
  display: grid;
  gap: var(--space-3);
}

.related-box a {
  font-size: 0.9375rem;
}

.related-links-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-6);
  margin-top: var(--space-6);
}

/* ==========================================================================
   Legal, support, 404
   ========================================================================== */

.legal-shell {
  padding: var(--space-8) 0 var(--space-9);
}

.legal-shell .container {
  max-width: 44rem;
}

.legal-shell h1 {
  font-size: clamp(2.25rem, 1.5rem + 2.4vw, 3.25rem);
}

.legal-updated {
  color: var(--ink-soft);
  font-size: 0.9375rem;
  margin-bottom: var(--space-8);
}

.legal-shell h2 {
  font-size: 1.5rem;
  margin-top: var(--space-8);
}

.legal-shell p,
.legal-shell li {
  color: var(--ink-soft);
}

.legal-shell ul {
  padding-left: 1.3rem;
  margin-bottom: var(--space-4);
}

.legal-shell li {
  margin-bottom: var(--space-2);
}

/* Support: two columns of plain text with hairlines, and a photograph where
   the two bordered cards and their icon rows used to be. */
.support-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-8);
  align-items: start;
}

.support-card {
  background: none;
  border: 0;
  border-radius: 0;
  padding: 0;
}

.support-card h2 {
  margin-top: 0;
  margin-bottom: var(--space-5);
  font-size: 1.5rem;
}

.support-visual img {
  width: 100%;
  border-radius: var(--radius);
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: var(--sage);
}

.contact-row {
  display: block;
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--line);
}

.contact-row:last-child {
  border-bottom: none;
}

.contact-row svg {
  display: none;
}

.contact-row .contact-label {
  display: block;
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: var(--space-2);
}

.contact-row .contact-value {
  font-size: 1.0625rem;
}

.notfound-shell {
  padding: var(--space-9) 0;
  max-width: 34rem;
}

.notfound-shell img {
  display: none;
}

.notfound-shell h1 {
  font-size: clamp(2.25rem, 1.5rem + 2.4vw, 3.25rem);
}

.notfound-shell p {
  color: var(--ink-soft);
}

.notfound-actions {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  margin-top: var(--space-6);
  flex-wrap: wrap;
}

/* ==========================================================================
   Dialogs
   ========================================================================== */

.notify-dialog {
  width: min(30rem, calc(100vw - 2rem));
  padding: 0;
  border: 0;
  border-radius: var(--radius);
  background: var(--cream);
  color: var(--ink);
}

.notify-dialog::backdrop {
  background: rgba(1, 38, 32, 0.45);
}

.notify-form {
  position: relative;
  padding: var(--space-7);
}

.notify-close {
  position: absolute;
  top: var(--space-5);
  inset-inline-end: var(--space-5);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink-soft);
  cursor: pointer;
}

.notify-close:hover {
  color: var(--ink);
}

.notify-close svg {
  width: 18px;
  height: 18px;
}

.notify-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.75rem;
  line-height: 1.15;
  margin: 0 var(--space-7) var(--space-4) 0;
}

.notify-body {
  color: var(--ink-soft);
  font-size: 0.9375rem;
  margin: 0 0 var(--space-6);
}

.notify-label {
  display: block;
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: var(--space-2);
}

.notify-input {
  width: 100%;
  font: inherit;
  padding: var(--space-3) 0;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  color: var(--ink);
  margin-bottom: var(--space-6);
}

.notify-input:focus-visible {
  outline: none;
  border-bottom-color: var(--ink);
}

/* Honeypot. Moved out of view rather than display:none — the bots worth
   catching skip fields that are display:none, and a real visitor never reaches
   it because it is aria-hidden and tabindex="-1". */
.notify-hp {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.notify-status {
  font-size: 0.9375rem;
  margin: var(--space-4) 0 0;
  min-height: 1.2em;
}

.notify-status.is-ok {
  color: var(--ink);
}

.notify-status.is-error {
  color: #8C3A3A;
}

.exit-dialog .email-cta-form {
  max-width: none;
}

/* ==========================================================================
   Motion
   One fade-up, 400ms over 16px, gated behind .js-anim so nothing is ever
   stuck invisible if the script fails. It is the only animation on the site:
   a marquee of the six readings the app logs ran under the hero for a while
   and came out again, so "one fade-up" is now the whole of it.
   ========================================================================== */

.js-anim .section-head,
.js-anim .feature-row,
.js-anim .bento,
.js-anim .vision-card,
.js-anim .final-cta,
.js-anim .support-card,
.js-anim .article-card {
  transition: opacity 0.4s ease, transform 0.4s ease;
}

.js-anim .section-head:not(.is-visible),
.js-anim .feature-row:not(.is-visible),
.js-anim .bento:not(.is-visible),
.js-anim .vision-card:not(.is-visible),
.js-anim .final-cta:not(.is-visible),
.js-anim .support-card:not(.is-visible),
.js-anim .article-card:not(.is-visible) {
  opacity: 0;
  transform: translateY(16px);
}

.blog-grid > *:nth-child(2) { transition-delay: 0.06s; }
.blog-grid > *:nth-child(3) { transition-delay: 0.12s; }

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 1023px) {
  :root {
    --section-y: 104px;
  }

  .blog-grid,
  .related-links-row,
  .bento {
    grid-template-columns: repeat(2, 1fr);
  }

  .bento-card.is-lead {
    grid-column: span 2;
  }

  .article-grid {
    grid-template-columns: 1fr;
  }

  .article-sidebar {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
  }

  .article-sidebar > * {
    flex: 1 1 240px;
  }

  .footer-top {
    grid-template-columns: 1fr 1fr 1fr;
  }

  .footer-brand {
    grid-column: 1 / -1;
  }
}

@media (max-width: 860px) {
  .main-nav,
  .header-store,
  .lang-dropdown {
    display: none;
  }

  .nav-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    justify-self: end;
  }

  .site-header .container {
    grid-template-columns: 1fr auto;
  }

  .feature-row,
  .final-cta,
  .support-grid,
  .faq-split {
    grid-template-columns: 1fr;
    gap: var(--space-6);
  }

  /* Stacked, the photograph goes under the heading rather than after eight
     accordions, where nobody would reach it, and it stops being sticky. */
  .faq-media {
    position: static;
    order: -1;
  }

  .faq-media img {
    aspect-ratio: 16 / 9;
  }

  .feature-row:nth-child(even) .feature-visual {
    order: 0;
  }

  .feature-list {
    gap: var(--space-8);
  }

  .scan-block {
    margin-bottom: var(--space-8);
  }

  .feature-copy {
    max-width: none;
  }

  .final-cta-media {
    order: -1;
  }

  .final-cta-media img {
    aspect-ratio: 3 / 2;
  }

  .vision-card {
    padding: var(--space-8) var(--space-6);
  }

  .hero {
    min-height: 0;
    padding: var(--space-9) 0 var(--space-8);
  }

  .hero-media img {
    object-position: 62% 40%;
  }

  /* The copy covers the whole frame at this width, so the horizontal ramp has
     nothing left to make room for and only serves to hide the photograph.
     Replaced with an even one, weighted to the foot where the badges sit.

     Heavier than the desktop pass, and it has to be: there the text sits on
     blurred foliage, here it sits on her, and she is the brightest thing in
     the frame. At these values the worst pixel under the headline measures
     5.9:1 and under the sentence 5.5:1. The picture reads as atmosphere at
     this width rather than as something anyone studies, so the trade is
     cheap. */
  .hero-media::after {
    background: linear-gradient(180deg,
      rgba(1, 38, 32, 0.76) 0%,
      rgba(1, 38, 32, 0.72) 28%,
      rgba(1, 38, 32, 0.93) 100%);
  }

  .footer-top {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 640px) {
  :root {
    --section-y: 80px;
    --header-height: 60px;
  }

  body {
    font-size: 16px;
  }

  .container {
    padding: 0 var(--space-5);
  }

  .blog-grid,
  .related-links-row,
  .bento {
    grid-template-columns: 1fr;
  }

  .bento-card,
  .bento-card.is-lead {
    grid-column: span 1;
    min-height: 0;
  }

  /* One column is too narrow for the lead card's drawing to sit behind its
     copy, so it rejoins the flow and takes the corner under the text the way
     the four cards beside it do. */
  .bento-card.is-lead .bento-art {
    position: relative;
    inset: auto;
    width: 62%;
    max-width: 200px;
    margin: var(--space-5) calc(var(--space-6) * -1) calc(var(--space-6) * -1) auto;
  }

  .blog-grid {
    gap: var(--space-7);
  }

  .footer-top {
    grid-template-columns: 1fr;
    gap: var(--space-6);
  }

  .footer-bottom {
    flex-direction: column;
    gap: var(--space-2);
  }

  .store-badges {
    align-items: flex-start;
  }

  .article-sidebar {
    flex-direction: column;
  }

  .article-cta {
    grid-template-columns: 1fr;
    gap: var(--space-5);
  }

  .article-cta-mark {
    width: 60px;
  }

  .email-cta-form {
    flex-direction: column;
    align-items: stretch;
  }

  .email-cta-button {
    width: 100%;
  }
}

/* ---------- Carb counter ----------
   generate_carbs.py. Built to work like the carb-counting apps people
   already use — a search pill, photo categories, foods in measured portions,
   a plate with a running total pinned to the bottom — in the site's own
   grammar: cream, linen and the card tints, hairlines, the two buttons.
   Bands alternate cream and linen so each part of the page has its own
   ground; nothing sits on a single wash. */

/* Hero: cream, tight, the search pill as the first thing under the title. */
.carb-hero {
  padding: var(--space-7) 0 var(--space-7);
  background: var(--cream);
}

.carb-hero h1 {
  font-size: clamp(2.25rem, 1.4rem + 3vw, 3.5rem);
  margin-bottom: var(--space-3);
  text-wrap: balance;
}

.carb-hero--food h1 {
  font-size: clamp(1.9rem, 1.2rem + 2.4vw, 2.75rem);
  max-width: 20em;
}

.carb-lede {
  font-size: 1.0625rem;
  color: var(--ink-soft);
  max-width: 36em;
  margin-bottom: var(--space-6);
}

.carb-crumbs {
  font-size: 0.875rem;
  color: var(--ink-soft);
  margin-bottom: var(--space-5);
}

.carb-crumbs a { color: var(--ink-soft); }
.carb-crumbs span { margin: 0 var(--space-2); }

/* The answer: the one sentence a food page exists for. */
.carb-answer {
  font-size: 1.1875rem;
  line-height: 1.55;
  max-width: 38em;
  margin-bottom: var(--space-6);
}

.carb-answer strong { font-weight: 600; }

/* ---- the search pill: a white rounded field on cream, the icon inside,
   the amount on the right. */
.carb-search { max-width: 44rem; margin: 0; }

.carb-search-pill {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 0 var(--space-4) 0 var(--space-5);
  min-height: 60px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
}

.carb-search-pill:focus-within { border-color: var(--ink); }

.carb-search-pill > svg {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  color: var(--ink-soft);
}

.carb-search-pill input[type="search"] {
  flex: 1;
  min-width: 0;
  font: inherit;
  font-size: 1.0625rem;
  padding: var(--space-3) 0;
  background: transparent;
  border: 0;
  color: var(--ink);
  -webkit-appearance: none;
}

.carb-search-pill input:focus { outline: none; }

.carb-search-grams {
  display: flex;
  align-items: center;
  gap: 4px;
  padding-left: var(--space-3);
  border-left: 1px solid var(--line);
  color: var(--ink-soft);
  font-size: 0.9375rem;
  white-space: nowrap;
}

.carb-search-grams input {
  width: 4em;
  font: inherit;
  font-size: 1rem;
  text-align: right;
  background: transparent;
  border: 0;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.carb-hint {
  font-size: 0.8125rem;
  color: var(--ink-soft);
  margin: var(--space-3) 0 0;
}

.carb-status {
  color: var(--ink-soft);
  font-size: 0.9375rem;
  margin: var(--space-4) 0 var(--space-2);
}

/* The hero on the hub: search on the left, the plate on the right, so the
   thing you are building is in view while you build it. */
.carb-hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(280px, 2fr);
  gap: var(--space-7);
  align-items: start;
}

.plate-panel {
  position: sticky;
  top: calc(var(--header-height) + var(--space-5));
  padding: var(--space-6);
  border-radius: var(--radius);
  background: var(--sage);
}

.plate-panel .plate-head { margin-bottom: var(--space-3); }
.plate-panel .plate-head h2 { font-size: 1.375rem; }

.plate-panel-total {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 56px;
  height: 56px;
  padding: 0 var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--plate);
  color: var(--lime);
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-variant-numeric: tabular-nums;
}

/* The drawing: the plate seen from above, in the art's own palette, filling
   with flat food shapes as portions are added. */
.plate-art {
  display: block;
  width: 100%;
  height: auto;
  max-width: 14rem;
  margin: 0 auto var(--space-4);
}

.plate-sheet .plate-art { max-width: 11rem; margin-bottom: var(--space-3); }

.plate-art-num {
  font-family: var(--font-display);
  font-size: 40px;
  fill: var(--ink);
  font-variant-numeric: tabular-nums;
}

.plate-art-sub {
  font-family: var(--font-body);
  font-size: 13px;
  fill: var(--ink-soft);
}

.plate-panel .plate-list { border-top-color: rgba(2, 50, 44, 0.18); }
.plate-panel .plate-item { border-bottom-color: rgba(2, 50, 44, 0.18); }
.plate-panel .plate-item-g input { border-bottom-color: rgba(2, 50, 44, 0.3); }
.plate-panel .plate-item-remove:hover { background: rgba(2, 50, 44, 0.08); }
.plate-panel .plate-empty { margin: var(--space-2) 0 var(--space-4); font-size: 0.9375rem; }
.plate-panel .plate-sum { padding-top: var(--space-3); }

/* With the panel in view there is no need for the bar on a wide screen. */
@media (min-width: 1024px) {
  body.has-plate-panel { padding-bottom: 0; }
  body.has-plate-panel .plate-bar { display: none; }
}

@media (max-width: 1023px) {
  .carb-hero-grid { grid-template-columns: 1fr; }
  .plate-panel { position: static; }
}

/* ---- bands */
.carb-band { padding: var(--space-8) 0; }

.carb-band-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2) var(--space-5);
  margin-bottom: var(--space-5);
}

.carb-band-head h2 {
  font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem);
  margin: 0;
}

.carb-band-head p {
  margin: 0;
  color: var(--ink-soft);
  font-size: 0.9375rem;
}

.carb-h2 {
  font-size: 1.5rem;
  margin: var(--space-8) 0 var(--space-4);
}

/* ---- category tiles: photo, name, count. A row that scrolls sideways on
   a phone, like the app's, and a grid where there is room. */
.carb-tiles {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--space-5);
}

.carb-tile {
  display: block;
  text-decoration: none;
  color: var(--ink);
}

.carb-tile img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-sm);
  background: var(--sage);
  margin-bottom: var(--space-3);
  transition: transform 0.2s ease;
}

.carb-tile:hover img { transform: scale(1.02); }

.carb-tile-name {
  display: block;
  font-weight: 500;
  line-height: 1.3;
}

.carb-tile-count {
  display: block;
  font-size: 0.8125rem;
  color: var(--ink-soft);
}

/* ---- food rows: name and portion on the left, per-100 g in the middle,
   the + on the right. Hairlines, no boxes. */
.carb-rows {
  border-top: 1px solid var(--line);
}

.carb-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--line);
}

.carb-row-main {
  display: block;
  min-width: 0;
  text-decoration: none;
  color: var(--ink);
}

.carb-row-name {
  display: block;
  font-weight: 500;
}

.carb-row-main:hover .carb-row-name { text-decoration: underline; }

.carb-row-sub {
  display: block;
  font-size: 0.875rem;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}

.carb-row-sub strong { color: var(--ink); font-weight: 600; }

.carb-row-100 {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  text-align: right;
  font-weight: 500;
}

.carb-row-100 small {
  display: block;
  font-size: 0.75rem;
  font-weight: 400;
  color: var(--ink-soft);
}

.carb-result-brand {
  color: var(--ink-soft);
  font-weight: 400;
}

/* The +: a forest disc, the one accent on the row. */
.carb-add-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--forest);
  color: var(--cream);
  cursor: pointer;
  flex-shrink: 0;
  transition: background-color 0.15s ease, transform 0.15s ease;
}

.carb-add-btn svg { width: 20px; height: 20px; }
.carb-add-btn:hover { background: var(--forest-press); }
.carb-add-btn.is-added { background: var(--plate); transform: scale(0.92); }

/* ---- steps */
/* An <ol> for the semantics; the badge is the number, so the list's own
   marker is switched off. */
.carb-steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-5);
  list-style: none;
  padding: 0;
  margin: 0;
}

.carb-step {
  padding: var(--space-6);
  border-radius: var(--radius);
  background: var(--cream);
}

.carb-step-n {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--plate);
  color: var(--lime);
  font-weight: 600;
  font-size: 0.9375rem;
  margin-bottom: var(--space-4);
}

.carb-step h3 {
  font-size: 1.25rem;
  margin-bottom: var(--space-2);
}

.carb-step p {
  margin: 0;
  font-size: 0.9375rem;
  color: var(--ink-soft);
}

.carb-faq { max-width: 44rem; }

/* ---- cards on a food page */
.carb-cards {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  gap: var(--space-5);
}

.carb-cards--stack { grid-template-columns: 1fr; max-width: 44rem; }

.carb-card {
  padding: var(--space-6);
  border-radius: var(--radius);
}

.carb-card.is-butter { background: var(--butter); }
.carb-card.is-sage { background: var(--sage); }
.carb-card.is-linen { background: var(--linen); }

.carb-card h2 {
  font-size: 1.25rem;
  margin-bottom: var(--space-4);
}

.carb-prose {
  max-width: 38em;
  padding: var(--space-2) var(--space-2);
}

.carb-prose h2 { font-size: 1.25rem; }
.carb-prose p { color: var(--ink-soft); margin: 0; }

/* Portion chips: radios styled as pills; the chosen one is ink. */
.carb-chips-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.carb-chip { position: relative; }

.carb-chip input[type="radio"] {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}

.carb-chip > span {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: var(--space-2) var(--space-4);
  border: 1px solid rgba(2, 50, 44, 0.25);
  border-radius: var(--radius-pill);
  font-size: 0.9375rem;
  cursor: pointer;
  background: transparent;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.carb-chip input:checked + span {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--cream);
}

.carb-chip input:focus-visible + span { outline: 2px solid var(--forest); outline-offset: 2px; }

.carb-chip--custom input[type="number"] {
  width: 4em;
  font: inherit;
  text-align: right;
  background: transparent;
  border: 0;
  border-bottom: 1px solid currentColor;
  color: inherit;
  padding: 0;
}

.carb-chip--custom input[type="number"]:focus { outline: none; }

.carb-addline {
  font-size: 1.0625rem;
  font-variant-numeric: tabular-nums;
  margin-bottom: var(--space-4);
}

.carb-addcard .btn svg { width: 18px; height: 18px; }

.carb-key {
  display: grid;
  gap: var(--space-3);
  font-variant-numeric: tabular-nums;
  margin: 0;
}

.carb-key div {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--line);
  font-size: 0.9375rem;
}

.carb-key div:last-child { border-bottom: 0; padding-bottom: 0; }
.carb-key dt { color: var(--ink-soft); }
.carb-key dd { margin: 0; font-weight: 600; }

/* ---- tables: hairline rows, right-aligned tabular figures. */
.carb-table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
  margin: 0;
}

.carb-table th,
.carb-table td {
  padding: var(--space-3) var(--space-3) var(--space-3) 0;
  border-bottom: 1px solid var(--line);
  text-align: right;
  vertical-align: baseline;
}

.carb-table tbody tr:last-child td { border-bottom: 0; }
.carb-table th:first-child, .carb-table td:first-child { text-align: left; }
.carb-table th:last-child, .carb-table td:last-child { padding-right: 0; }

.carb-table thead th {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.carb-table td.is-key { font-weight: 600; }
.carb-table tr.is-base td { color: var(--ink-soft); }
.carb-table--decl td.is-sub { padding-left: var(--space-5); color: var(--ink-soft); }

.carb-source {
  font-size: 0.8125rem;
  color: var(--ink-soft);
  margin: var(--space-4) 0 0;
}

.carb-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.carb-chips a {
  display: inline-block;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  text-decoration: none;
  font-size: 0.9375rem;
  background: var(--cream);
}

.carb-chips a:hover { border-color: var(--ink); }

.carb-links { display: grid; gap: var(--space-2); }

/* ---- category page head: title left, photo right. */
.carb-cat-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-6);
  align-items: center;
}

.carb-cat-head h1 { margin-bottom: var(--space-3); }

.carb-cat-photo {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: var(--radius);
  background: var(--sage);
}

/* ---- the plate bar: pinned to the bottom, the plate's dark ground, the
   total in a cream disc. Pages that carry it pad the body so the footer's
   last line is never hidden under it. */
body.has-plate { padding-bottom: 88px; }

.plate-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 90;
  background: var(--plate);
  color: var(--plate-ink);
  padding: var(--space-3) 0;
  box-shadow: 0 -1px 0 var(--line-dark);
}

.plate-bar .container {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.plate-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 64px;
  height: 64px;
  padding: 0 var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

.plate-bar.is-bump .plate-badge { animation: plate-bump 0.35s ease; }

@keyframes plate-bump {
  0% { transform: scale(1); }
  40% { transform: scale(1.12); }
  100% { transform: scale(1); }
}

.plate-copy {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  line-height: 1.3;
}

.plate-copy strong { font-weight: 600; }

.plate-copy span {
  font-size: 0.875rem;
  color: rgba(249, 241, 230, 0.78);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.plate-bar .btn-primary {
  background: var(--lime);
  color: var(--plate);
}

.plate-bar .btn-primary:hover { background: #e2f03a; color: var(--plate); }

/* The sheet: the notify dialog's shell, wider, with the list in it. */
.plate-dialog {
  border: 0;
  padding: 0;
  background: transparent;
  max-width: none;
  max-height: none;
  width: 100%;
  height: 100%;
  margin: 0;
}

.plate-dialog::backdrop { background: rgba(1, 38, 32, 0.45); }

.plate-sheet {
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  width: min(100%, 44rem);
  max-height: 85vh;
  overflow: auto;
  background: var(--cream);
  color: var(--ink);
  border-radius: var(--radius) var(--radius) 0 0;
  padding: var(--space-6) var(--space-6) var(--space-7);
}

.plate-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-4);
}

.plate-head h2 { margin: 0; font-size: 1.5rem; }
.plate-head .notify-close { position: static; }

.plate-list { border-top: 1px solid var(--line); }

.plate-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto auto;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--line);
}

.plate-item-name { font-weight: 500; min-width: 0; overflow-wrap: anywhere; }
.plate-item-name a { text-decoration: none; }

.plate-item-g {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--ink-soft);
  font-size: 0.9375rem;
}

.plate-item-g input {
  width: 4.5em;
  font: inherit;
  text-align: right;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line);
  color: var(--ink);
  padding: 2px 0;
  font-variant-numeric: tabular-nums;
}

.plate-item-carbs {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.plate-item-remove {
  width: 32px;
  height: 32px;
  padding: 6px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
}

.plate-item-remove:hover { background: var(--linen); color: var(--ink); }

.plate-empty { color: var(--ink-soft); margin: var(--space-4) 0; }

.plate-sum {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-4);
  padding: var(--space-4) 0;
  font-variant-numeric: tabular-nums;
}

.plate-sum > span:first-child { color: var(--ink-soft); }
.plate-sum strong { font-size: 1.5rem; font-family: var(--font-display); font-weight: 400; }
.plate-sum > span:last-child { color: var(--ink-soft); font-size: 0.9375rem; }

.plate-hint { font-size: 0.8125rem; color: var(--ink-soft); }

.plate-actions { display: flex; gap: var(--space-4); }

@media (max-width: 1023px) {
  .carb-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .carb-steps { grid-template-columns: 1fr; }
  .carb-cards { grid-template-columns: 1fr; }
  .carb-cat-head { grid-template-columns: 1fr; }
  .carb-cat-photo { aspect-ratio: 21 / 9; }
}

@media (max-width: 640px) {
  .carb-band { padding: var(--space-7) 0; }

  /* The tiles become the app's sideways row. The container's padding is
     re-applied inside the scroller so the first tile lines up with the
     heading and the last one can still run to the edge. */
  .carb-tiles {
    display: flex;
    gap: var(--space-4);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    margin: 0 calc(var(--space-6) * -1);
    padding: 0 var(--space-6) var(--space-2);
    -webkit-overflow-scrolling: touch;
  }

  .carb-tile { flex: 0 0 44%; scroll-snap-align: start; }

  .carb-row { grid-template-columns: minmax(0, 1fr) auto; }
  .carb-row-100 { display: none; }

  .carb-search-pill { padding-left: var(--space-4); min-height: 56px; }

  .carb-table th, .carb-table td { font-size: 0.875rem; padding-right: var(--space-2); }

  .plate-badge { min-width: 56px; height: 56px; font-size: 1.125rem; }
  .plate-item { grid-template-columns: minmax(0, 1fr) auto auto; }
  .plate-item-carbs { grid-column: 1; font-size: 0.9375rem; }
  .plate-sheet { padding: var(--space-5) var(--space-4) var(--space-6); }
}
