/* HeyHi design system: the base. The page and its line system, type, layout, links, buttons, a product's status and
   photography. Pages compose from these; their own stylesheets only arrange them. */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 24px);
  interpolate-size: allow-keywords;
}

/* The page stays put behind the phone menu and any popup */
html.menu-open,
html:has(dialog[open]) { overflow: hidden; }

body {
  margin: 0;
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: var(--text-body);
  line-height: var(--leading-text);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-kerning: normal;
  overflow-x: clip;
}

img, svg, video, canvas { max-width: 100%; }
img { display: block; height: auto; }
a { color: inherit; }
button, input, select, textarea { font: inherit; color: inherit; }
h1, h2, h3, h4 { margin: 0; font-family: var(--font-display); font-weight: 400; text-wrap: balance; }
p { margin: 0; text-wrap: pretty; }
ul, ol { margin: 0; padding: 0; }
figure, blockquote, dl, dd { margin: 0; }
::selection { background: var(--amber-soft); color: var(--c-ink); }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 3px; }

/* Hidden means hidden, even for elements whose class sets a display */
[hidden] { display: none !important; }

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

.skip-link {
  position: absolute; left: 16px; top: -100px; z-index: 100; padding: 10px 16px; border-radius: var(--radius-sm);
  background: var(--c-ink); color: var(--c-paper); font-weight: 600; text-decoration: none;
}
/* Shown to keyboard users, including when back-to-top hands focus to it, but not after a click */
.skip-link:focus-visible { top: 12px; }

/* ---------- The line system ---------- */
/* Two rails run down the page a little outside the content's edges, from under the header to the footer, and every
   section after the first is ruled off right across the page, so the page reads as one drawn frame. The rails are one
   element behind everything (main::before); a band with a background of its own (panel, night) covers them and draws
   its own, in its own line colour. On phones the margins are too narrow for rails, so only the rules remain. */
:root { --frame-inset: clamp(14px, 2.1vw, 30px); }
main { position: relative; display: block; }
@media (min-width: 48em) {
  main::before {
    content: ""; position: absolute; inset: 0 calc(var(--rail) - var(--frame-inset)); z-index: 0; pointer-events: none;
    border-inline: 1px solid var(--c-line);
  }
  :is(.section--panel, .section--tint, .section--night, .surface-night.has-rails)::before {
    content: ""; position: absolute; inset: 0 calc(var(--rail) - var(--frame-inset)); pointer-events: none;
    border-inline: 1px solid var(--line);
  }
}

/* A crosshair where a rule meets a rail, for the one or two places on a page that deserve the mark. Place it in a
   positioned box: .cross--start sits on the left rail, .cross--end on the right; both sit on the box's top edge. */
.cross {
  position: absolute; top: -5px; z-index: 1; width: 11px; height: 11px; pointer-events: none;
  background:
    linear-gradient(var(--ink-mute), var(--ink-mute)) center / 11px 1px no-repeat,
    linear-gradient(var(--ink-mute), var(--ink-mute)) center / 1px 11px no-repeat;
}
.cross--start { left: calc(var(--rail) - var(--frame-inset) - 5px); }
.cross--end { right: calc(var(--rail) - var(--frame-inset) - 5px); }
@media (max-width: 47.99em) { .cross { display: none; } }

/* A hairline that draws itself across when it arrives (data-reveal="line"), or simply sits there */
.rule { display: block; height: 1px; border: 0; margin: 0; background: var(--line); }
.rule--strong { background: var(--line-strong); }

/* ---------- Layout ---------- */
/* The page's column: content up to --content wide, with the gutter on either side */
.wrap {
  position: relative;
  width: 100%;
  max-width: calc(var(--content) + 2 * var(--gutter));
  margin-inline: auto;
  padding-left: max(var(--gutter), env(safe-area-inset-left, 0px));
  padding-right: max(var(--gutter), env(safe-area-inset-right, 0px));
}

/* A band of the page. Plain sections sit on paper and are ruled off from the one before; a panel band is 3% deeper; a
   night band is dark, re-pointing the colour roles (00_tokens.css) so everything in it reads right. */
/* Everything in main sits above the rails (main::before), and the bands with a background cover them */
main > * { position: relative; }
.section { position: relative; padding-block: var(--section); }
main > section + section { border-top: 1px solid var(--line); }
.section--panel, .section--tint { --surface: var(--c-panel); background: var(--c-panel); }
.section--night { background: var(--surface); color: var(--ink); border-top-color: transparent; }
.section--night + .section { border-top-color: transparent; }

/* A section's opening: its index and label, its headline, and the line under it */
.section-head { display: grid; gap: var(--space-5); max-width: 54rem; margin-bottom: clamp(48px, 6.4vw, 104px); }
.section-head .kicker { margin-bottom: var(--space-1); }
/* Headline on the left, its paragraph on the right, meeting at the baseline: for a section that opens wide */
@media (min-width: 64em) {
  .section-head--split {
    max-width: none; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); column-gap: calc(var(--col-gap) * 2); align-items: end;
  }
  .section-head--split > .kicker { grid-column: 1 / -1; }
  .section-head--split > .t-lead { padding-bottom: 0.35em; }
}

/* Two columns with a rule between them: a narrow one that holds the section's head (and stays in view on wide screens,
   .split--sticky), and a wide one that holds the substance */
.split { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-7); }
/* --split-pad is the room either side of the rule, which anything lining up with the rule can use */
:root { --split-pad: clamp(32px, 4vw, 72px); }
@media (min-width: 64em) {
  /* The head takes a third of the frame from rail to rail, so the rule lands where the page's other thirds divide */
  .split { grid-template-columns: calc((100% + 2 * var(--frame-inset)) / 3 - var(--frame-inset)) minmax(0, 1fr); gap: 0; }
  .split__aside { padding-right: var(--split-pad); }
  .split__main { min-width: 0; padding-left: var(--split-pad); border-left: 1px solid var(--line); }
  .split--sticky .split__aside > * { position: sticky; top: calc(var(--header-h) + 40px); }
  .split .section-head { margin-bottom: 0; }
}

/* A list ruled off row by row, each row led by its number: the house way to list a few substantial things */
.rows { list-style: none; counter-reset: row; border-bottom: 1px solid var(--line); }
.rows > li { counter-increment: row; position: relative; border-top: 1px solid var(--line); }
.row-index { font-family: var(--font-mono); font-size: var(--text-label); letter-spacing: var(--tracking-label); color: var(--ink-mute); font-variant-numeric: tabular-nums; }

/* ---------- Type ---------- */
/* Headlines are the serif, light and close-set; at display sizes the optical size follows automatically */
.t-hero { font-family: var(--font-display); font-size: var(--text-hero); font-weight: 400; line-height: var(--leading-hero); letter-spacing: var(--tracking-hero); }
.t-title { font-family: var(--font-display); font-size: var(--text-title); font-weight: 400; line-height: var(--leading-title); letter-spacing: var(--tracking-title); }
.t-heading { font-family: var(--font-display); font-size: var(--text-heading); font-weight: 400; line-height: var(--leading-heading); letter-spacing: var(--tracking-heading); }
/* A row's or a card's title is the grotesk, firm and small */
.t-subheading { font-family: var(--font-text); font-size: var(--text-subheading); font-weight: 600; line-height: 1.25; letter-spacing: -0.012em; }
.t-lead { font-size: var(--text-lead); line-height: 1.5; color: var(--ink-soft); max-width: 34em; letter-spacing: -0.006em; }
.t-small { font-size: var(--text-small); line-height: 1.55; color: var(--ink-soft); }
.t-caption { font-size: var(--text-caption); line-height: 1.45; color: var(--ink-mute); }
/* Metadata: indices, statuses, times. Mono, small, in capitals, tracked out. */
.t-label {
  font-family: var(--font-mono); font-size: var(--text-label); font-weight: 500; line-height: 1.3;
  letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--ink-mute);
}
.tnum { font-variant-numeric: tabular-nums; }

/* A section's index and label, as "01 ── Products": the number in ink, a short rule, the label */
.kicker {
  display: flex; align-items: center; gap: 14px;
  font-family: var(--font-mono); font-size: var(--text-label); font-weight: 500; line-height: 1.3;
  letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--ink-mute);
}
.kicker__index { display: inline-flex; align-items: center; gap: 14px; color: var(--ink); font-variant-numeric: tabular-nums; }
.kicker__index::after { content: ""; width: 32px; height: 1px; background: var(--line-strong); }

/* ---------- Links ---------- */
/* A link inside a sentence, or a button that reads like one: an amber underline that turns ink */
.text-link {
  display: inline; padding: 0; border: 0; background: none; cursor: pointer;
  color: inherit; font-weight: 600; text-decoration: underline; text-decoration-color: var(--amber);
  text-decoration-thickness: 1.5px; text-underline-offset: 4px;
  transition: text-decoration-color var(--dur-fast);
}
.text-link:hover { text-decoration-color: currentColor; }

/* A link that leads on to more: its words, then an arrow that moves when it's pointed at, and an underline that draws
   in from the left */
.arrow-link {
  display: inline-flex; align-items: center; gap: 8px; padding-block: 4px;
  color: inherit; font-weight: 600; text-decoration: none;
  background: linear-gradient(currentColor, currentColor) left bottom / 0% 1px no-repeat;
  transition: background-size var(--dur-ui) var(--ease-out);
}
.arrow-link .icon { width: 16px; height: 16px; transition: transform var(--dur-ui) var(--ease-out); }
.arrow-link:hover { background-size: 100% 1px; }
.arrow-link:hover .icon { transform: translateX(3px); }
.arrow-link:hover .icon--arrow-up-right { transform: translate(2px, -2px); }

/* ---------- Icons and the mark ---------- */
.icon { width: 1.1em; height: 1.1em; flex: none; fill: currentColor; vertical-align: -0.15em; }
.mark { display: block; width: 28px; height: auto; aspect-ratio: 135 / 124; fill: currentColor; color: inherit; }

/* ---------- Buttons ---------- */
/* One shape for every button: a pill, with its label and an optional icon. --signal is HeyHi amber and marks the one
   action a section leads with; --ink is the firm one for the header and quiet places; --ghost sits beside either. On
   hover a fill rises from the bottom edge; an arrow moves on, and a press settles it a pixel. */
.btn {
  --btn-h: 48px; --btn-bg: transparent; --btn-fg: var(--ink); --btn-border: transparent; --btn-wipe: transparent;
  position: relative; isolation: isolate; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-height: var(--btn-h); padding: 0 24px; border-radius: var(--radius-round);
  border: 1px solid var(--btn-border); background: var(--btn-bg); color: var(--btn-fg);
  font-family: var(--font-text); font-size: 15.5px; font-weight: 600; letter-spacing: -0.005em; line-height: 1.1;
  text-align: center; text-decoration: none; white-space: nowrap; cursor: pointer;
  transition: color var(--dur-fast), border-color var(--dur-fast), background-color var(--dur-fast), transform var(--dur-fast) var(--ease-out);
}
.btn::before {
  content: ""; position: absolute; inset: -1px; z-index: -1; border-radius: inherit; background: var(--btn-wipe);
  transform: translate3d(0, 102%, 0); transition: transform 0.55s var(--ease-out);
}
.btn:hover::before { transform: none; }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.6; cursor: progress; }
.btn .icon { width: 17px; height: 17px; transition: transform var(--dur-ui) var(--ease-out); }
.btn:hover .icon--arrow, .btn:hover .icon--arrow-right { transform: translateX(3px); }
.btn:hover .icon--arrow-up-right { transform: translate(2px, -2px); }
.btn--signal { --btn-bg: var(--amber); --btn-fg: var(--c-ink); --btn-wipe: var(--amber-hover); }
.btn--signal:active { --btn-bg: var(--amber-press); }
.btn--ink { --btn-bg: var(--ink); --btn-fg: var(--on-ink); --btn-wipe: color-mix(in srgb, var(--ink) 84%, var(--surface)); }
.btn--ghost { --btn-border: var(--line-strong); --btn-fg: var(--ink); --btn-wipe: color-mix(in srgb, var(--ink) 7%, transparent); }
.btn--ghost:hover { --btn-border: color-mix(in srgb, var(--ink) 40%, transparent); }
.btn--sm { --btn-h: 38px; padding: 0 16px; font-size: 14.5px; gap: 8px; }
.btn--sm .icon { width: 15px; height: 15px; }
.btn--block { width: 100%; }
/* A button's number, such as the phone line it rings, keeps its figures even */
.btn .tnum { font-variant-numeric: tabular-nums; }

/* A row of buttons */
.actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }

/* ---------- A product's status ---------- */
/* Live, Beta or Coming soon, in words with a mark, never as a pill: live is a solid amber dot that breathes, beta a
   half-filled ring, coming soon an empty one. Written by the product_status helper. */
.status {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-text); font-size: var(--text-caption); font-weight: 600; line-height: 1.2;
  letter-spacing: 0; color: var(--ink-soft); white-space: nowrap;
}
.status__mark { position: relative; width: 7px; height: 7px; flex: none; border-radius: 50%; border: 1.25px solid currentColor; }
.status--live { color: var(--ink); }
.status--live .status__mark { background: var(--amber); border-color: var(--amber); }
.status--live .status__mark::after {
  content: ""; position: absolute; inset: -1.25px; border-radius: 50%; background: var(--amber);
  animation: status-breathe 2.4s var(--ease-in-out) infinite;
}
.status--beta .status__mark { background: linear-gradient(90deg, currentColor 50%, transparent 50%); }
.status--coming-soon .status__mark { background: transparent; }
@keyframes status-breathe { 0% { opacity: 0.55; transform: scale(1); } 70%, 100% { opacity: 0; transform: scale(2.6); } }

/* ---------- Photography ---------- */
/* Real photographs of real businesses, in natural light, with people in them. Each sits in a frame that crops it to the
   layout (cover) around its subject, which data-focus places: any of left, right, top and bottom, such as
   data-focus="left top" (the centre otherwise). Left and right keep that edge of the photograph in the frame, so a
   subject at the edge, such as a face, is never cut by a narrow frame; top and bottom lean that way. A stylesheet can
   set --focus-x and --focus-y exactly instead. A fine grain sits over every photograph, so they share one stock, and the
   frame shows warm paper while the photograph loads. */
.photo {
  position: relative; overflow: hidden; border-radius: var(--radius-lg);
  background: var(--c-panel-deep);
  isolation: isolate;
}
.photo img { width: 100%; height: 100%; object-fit: cover; object-position: var(--focus-x, 50%) var(--focus-y, 50%); }
.photo::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none; opacity: 0.07; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1.2 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* A photograph still to come: a blank holder that fills the same frame, a little deeper than the panel it sits on,
   with one quiet mono label in its corner (ProductsHelper#photo_tag) */
.photo__holder {
  position: absolute; inset: 0; display: block;
  background: color-mix(in srgb, var(--c-panel-deep) 78%, var(--c-panel));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c-ink) 6%, transparent);
}
.photo__holder::before {
  content: "Image"; position: absolute; left: clamp(14px, 1.6vw, 22px); bottom: clamp(12px, 1.4vw, 18px);
  font-family: var(--font-mono); font-size: var(--text-label); font-weight: 500; line-height: 1;
  letter-spacing: var(--tracking-label); text-transform: uppercase; color: color-mix(in srgb, var(--c-ink) 45%, transparent);
}
.photo:has(.photo__holder)::after { opacity: 0.05; mix-blend-mode: multiply; }
.photo[data-focus~="left"] { --focus-x: 0%; }
.photo[data-focus~="right"] { --focus-x: 100%; }
.photo[data-focus~="top"] { --focus-y: 22%; }
.photo[data-focus~="bottom"] { --focus-y: 78%; }

/* A scene: a photograph with one product screen in it. The screen floats over the photograph's top right, or its top
   left with data-card="left", inset by --card-x and --card-y; on phones it sits across the photograph's lower edge,
   half in the scene. */
.scene { position: relative; }
.scene__photo { aspect-ratio: var(--scene-ratio, 16 / 9); }
.scene .scene__card {
  position: absolute; z-index: 2;
  top: var(--card-y, 10%); right: var(--card-x, 5%);
  width: min(var(--card-w, 380px), 44%);
}
.scene[data-card="left"] .scene__card { right: auto; left: var(--card-x, 5%); }
@media (max-width: 47.99em) {
  .scene__photo { aspect-ratio: var(--scene-ratio-sm, 4 / 3.4); border-radius: var(--radius-md); }
  .scene .scene__card, .scene[data-card="left"] .scene__card { position: relative; inset: auto; width: auto; margin: -72px var(--space-3) 0; }
}

/* A page's opening scene that breaks out of the column to the window's full width, framed back to the content's edges
   until the page scrolls, when it opens out to the full width (12_motion.css). Its card keeps to the content's edge
   throughout. On phones it stays in the column. */
@media (min-width: 48em) {
  .scene--open {
    --edge: max(var(--gutter), calc((100vw - var(--content)) / 2));
    width: 100vw; margin-inline: calc(50% - 50vw);
    clip-path: inset(0 var(--edge) round var(--radius-lg) var(--radius-lg) 0 0);
  }
  .scene--open .scene__photo { border-radius: 0; }
  .scene--open .scene__card { right: calc(var(--edge) + var(--card-x, 4%)); }
  .scene--open[data-card="left"] .scene__card { right: auto; left: calc(var(--edge) + var(--card-x, 4%)); }
  /* A photograph still to come keeps its label inside the frame's closed edges, where it can be seen */
  .scene--open .photo__holder::before { left: calc(var(--edge) + clamp(14px, 1.6vw, 22px)); }
}

/* ---------- Motion preferences ---------- */
@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; }
}
