/* ==========================================================================
   Troll Games — Armadillo Throw
   Holding page. Static HTML + CSS, self-hosted fonts, zero external requests.

   Spacing architecture: every element is reset to margin 0, and all vertical
   rhythm comes from `gap` on flex containers. Nothing sets both padding and
   margin for the same purpose, so no two spacing rules can cancel each other.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Fonts — self-hosted, latin subset, variable. See fonts/LICENSES.md.
   Fredoka carries the display voice: rounded and built, in keeping with a
   world of stacked stone. Nunito Sans shares its rounded terminals at text
   sizes without competing with it.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: 'Fredoka';
  src: url('fonts/fredoka-variable-latin.woff2') format('woff2');
  font-weight: 300 600;
  font-stretch: 75% 125%;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Nunito Sans';
  src: url('fonts/nunito-sans-variable-latin.woff2') format('woff2');
  font-weight: 200 1000;
  font-stretch: 75% 125%;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   Palette — warm earth, moss and gold, taken from the game itself.
   Every other colour is derived from these.

   --nugget is the in-game currency colour and is deliberately rare: it appears
   exactly twice on the page, on the tagline and on link underlines at hover.
   It is never used for the axis, section labels, body text or borders.

   --pitch is used in exactly one place: the footer band.
   -------------------------------------------------------------------------- */

:root {
  --loam:   #26221E;
  --bark:   #34302B;
  --pitch:  #171513;
  --bone:   #F2EADD;
  --ash:    #C9BFAE;
  --moss:   #B8C7A1;
  --nugget: #FDC400;

  /* Derived. Static fallbacks first, color-mix second where supported. */
  --text:        var(--bone);
  --text-muted:  var(--ash);
  --rule:        #767D66;
  --tick-minor:  #555748;
  --tick-major:  #767D66;
  --surface:     var(--bark);
}

@supports (color: color-mix(in srgb, red, blue)) {
  :root {
    --rule:       color-mix(in srgb, var(--moss) 55%, var(--loam));
    --tick-minor: color-mix(in srgb, var(--moss) 32%, var(--loam));
    --tick-major: color-mix(in srgb, var(--moss) 55%, var(--loam));
  }
}

/* Brand colours, used only as the hover and focus state of their own icon. */
:root {
  --brand-instagram: #E4405F;
  --brand-x:         #FFFFFF;
  --brand-mastodon:  #6364FF;
  --brand-youtube:   #FF0000;
  --brand-discord:   #5865F2;
}

/* --------------------------------------------------------------------------
   Type scale — a ~1.25 ratio, fluid between 360px and 1400px.
   -------------------------------------------------------------------------- */

:root {
  --text-xs: clamp(0.78rem, 0.76rem + 0.10vw, 0.86rem);
  --text-sm: clamp(0.88rem, 0.85rem + 0.13vw, 0.97rem);
  --text-md: clamp(1.03rem, 0.99rem + 0.20vw, 1.16rem);
  --text-lg: clamp(1.22rem, 1.13rem + 0.42vw, 1.50rem);
  --text-xl: clamp(1.42rem, 1.20rem + 0.95vw, 2.10rem);

  --space-1: 0.5rem;
  --space-2: 0.875rem;
  --space-3: 1.5rem;
  --space-4: 2.5rem;
  --space-5: 4rem;
  --space-6: clamp(3.5rem, 1.8rem + 6.5vw, 7rem);

  --gutter: clamp(1.125rem, 0.5rem + 2.5vw, 3rem);

  /* Mobile baseline. Both widen at min-width breakpoints near the end of the
     file, so the page fills a wide window instead of stranding a narrow
     column in it. */
  --measure: 60ch;
  --page-max: 1080px;

  /* Marker offsets are compressed so the widest label still fits at 320px. */
  --mark-scale: 0.45;

  /* How far the prose column follows its marker along the range. Zero on
     mobile, opened up at desktop width. */
  --cascade: 0;
}

/* --------------------------------------------------------------------------
   Reset
   -------------------------------------------------------------------------- */

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

:where(body, h1, h2, p, ul, li, figure) {
  margin: 0;
  padding: 0;
}

:where(ul) {
  list-style: none;
}

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

/* --------------------------------------------------------------------------
   Background pattern — one 240x240 inline-SVG tile as a data URI.
   Motifs are drawn from this game's own world: a mountain ridge, a curled
   armadillo, wind lines, an arc of trajectory, a club, and a row of
   measurement ticks along the tile's baseline. Static; it never animates.
   The footer band paints over it with an opaque colour.
   -------------------------------------------------------------------------- */

body {
  min-height: 100vh; /* Fallback for browsers without dynamic viewport units. */
  min-height: 100dvh;
  background-color: var(--loam);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240' viewBox='0 0 240 240'%3E%3Cg fill='none' stroke='%23B8C7A1' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round' opacity='.06'%3E%3Cpath d='M14 106 42 62 57 80 78 48 108 106'/%3E%3Cpath d='M60 76 69 65'/%3E%3Ccircle cx='178' cy='58' r='18'/%3E%3Ccircle cx='178' cy='58' r='7'/%3E%3Cpath d='M178 40v9M192 68l-8-5M164 68l8-5'/%3E%3Cpath d='M150 124q20-7 38 0M156 136q24-8 44 0M164 148q16-6 30 0'/%3E%3Cpath d='M110 202q58-64 116-18'/%3E%3Cpath d='M34 208 64 180'/%3E%3Cellipse cx='82' cy='166' rx='21' ry='11' transform='rotate(-42 82 166)'/%3E%3C/g%3E%3Cg stroke='%23B8C7A1' stroke-width='1.4' opacity='.09'%3E%3Cpath d='M0 226v10M24 230v6M48 230v6M72 230v6M96 230v6M120 226v10M144 230v6M168 230v6M192 230v6M216 230v6'/%3E%3C/g%3E%3C/svg%3E");
  background-repeat: repeat;
  background-position: center top;
  color: var(--text);
  font-family: 'Nunito Sans', 'Segoe UI', system-ui, sans-serif;
  font-size: var(--text-md);
  line-height: 1.65;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  overflow-wrap: break-word;
}

/* --------------------------------------------------------------------------
   Page frame
   -------------------------------------------------------------------------- */

.page {
  width: min(100% - (var(--gutter) * 2), var(--page-max));
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  padding-block: clamp(3rem, 1.5rem + 5vw, 6rem) var(--space-6);
}

.main {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

.section {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* The prose column follows its own marker down the range once there is room
   for it to do so. --cascade is 0 below the desktop breakpoint. */
.prose {
  max-width: var(--measure);
  margin-inline-start: calc(var(--mark, 0%) * var(--cascade));
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  text-wrap: pretty;
}

/* --------------------------------------------------------------------------
   Signature element — the horizontal measurement axis.

   Minor and major ticks rise from a ruled baseline. The section marker is the
   only tick that descends below the line, and its horizontal offset advances
   from left to right as you move down the page: vertical progress through the
   document is read as horizontal distance travelled. The offsets are the
   structure, not decoration — they are what makes each section a position on
   a range rather than an item in a list.

   There is exactly one ruler per section. The first section's axis is the
   start of the range; the footer carries the terminus.
   -------------------------------------------------------------------------- */

/* No `--mark` default is declared here on purpose. A direct declaration on
   .axis would beat the value inherited from the section, regardless of the
   ancestor's specificity, and every marker would collapse to zero. The default
   is supplied at the point of use instead, via the var() fallback below. */
.axis {
  display: flex;
  flex-direction: column;
}

/* The ticks are chiselled, not machined: each one differs slightly in length,
   angle, weight and spacing. The tile is 720px so the irregularity does not
   read as a repeat at any realistic width — a short tile would give the game
   away immediately.

   The ticks are SVG masks rather than SVG backgrounds because a data URI is a
   separate document and cannot see this file's custom properties. Tinting a
   mask with background-color keeps all three palette tokens live, so the ruler
   still follows the palette. The baseline stays a plain gradient: it must be
   unbroken at every width, which a tiled asset cannot guarantee. */
.axis__ruler {
  position: relative;
  height: 14px;
  background-image: linear-gradient(var(--rule), var(--rule));
  background-size: 100% 1px;
  background-position: 0 13px;
  background-repeat: no-repeat;
}

.axis__ruler::before,
.axis__ruler::after {
  content: '';
  position: absolute;
  inset: 0;
  -webkit-mask-repeat: repeat-x;
          mask-repeat: repeat-x;
  -webkit-mask-size: 720px 14px;
          mask-size: 720px 14px;
  -webkit-mask-position: 0 0;
          mask-position: 0 0;
}

.axis__ruler::before {
  background-color: var(--tick-major);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='720' height='14' viewBox='0 0 720 14'%3E%3Cg fill='none' stroke='%23fff' stroke-linecap='round'%3E%3Cpath stroke-width='1.3' d='M578.1 1.7L579.0 13.5'/%3E%3Cpath stroke-width='1.4' d='M672.9 1.4L673.5 13.5'/%3E%3Cpath stroke-width='1.5' d='M2.0 1.2L2.0 13.5M193.1 1.7L192.5 13.5M288.0 1.3L288.4 13.5M383.8 1.8L383.7 13.5M478.7 1.9L478.2 13.5'/%3E%3Cpath stroke-width='1.6' d='M96.3 1.7L95.5 13.5'/%3E%3C/g%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='720' height='14' viewBox='0 0 720 14'%3E%3Cg fill='none' stroke='%23fff' stroke-linecap='round'%3E%3Cpath stroke-width='1.3' d='M578.1 1.7L579.0 13.5'/%3E%3Cpath stroke-width='1.4' d='M672.9 1.4L673.5 13.5'/%3E%3Cpath stroke-width='1.5' d='M2.0 1.2L2.0 13.5M193.1 1.7L192.5 13.5M288.0 1.3L288.4 13.5M383.8 1.8L383.7 13.5M478.7 1.9L478.2 13.5'/%3E%3Cpath stroke-width='1.6' d='M96.3 1.7L95.5 13.5'/%3E%3C/g%3E%3C/svg%3E");
}

.axis__ruler::after {
  background-color: var(--tick-minor);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='720' height='14' viewBox='0 0 720 14'%3E%3Cg fill='none' stroke='%23fff' stroke-linecap='round'%3E%3Cpath stroke-width='0.9' d='M145.3 6.5L146.2 13.5M271.4 8.0L271.3 13.5M337.2 8.0L337.2 13.5M366.5 6.7L366.2 13.5M527.9 7.7L528.4 13.5'/%3E%3Cpath stroke-width='1.0' d='M62.2 6.4L61.9 13.5M81.0 6.6L81.7 13.5M178.0 7.7L177.9 13.5M625.7 6.6L626.3 13.5'/%3E%3Cpath stroke-width='1.1' d='M14.1 7.5L13.7 13.5M47.8 7.6L48.5 13.5M111.6 8.1L112.5 13.5M239.7 7.2L240.8 13.5M254.5 7.3L254.0 13.5M414.0 7.3L413.2 13.5M606.2 7.8L606.7 13.5M642.2 7.7L642.8 13.5M705.0 6.4L705.6 13.5'/%3E%3Cpath stroke-width='1.2' d='M32.4 6.9L32.1 13.5M126.5 6.7L127.2 13.5M206.5 8.2L207.1 13.5M223.5 7.7L224.6 13.5M354.2 6.9L353.7 13.5M433.0 6.5L433.9 13.5M497.0 7.2L497.3 13.5M511.8 6.6L512.4 13.5'/%3E%3Cpath stroke-width='1.3' d='M159.8 6.9L159.8 13.5M303.2 6.5L303.1 13.5M319.6 7.8L320.6 13.5M400.7 8.0L401.4 13.5M446.4 6.9L445.7 13.5M462.4 7.9L462.1 13.5M544.0 7.4L544.3 13.5M558.8 6.9L559.2 13.5M594.0 6.6L593.3 13.5M656.1 7.0L657.0 13.5M686.0 6.6L685.5 13.5'/%3E%3C/g%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='720' height='14' viewBox='0 0 720 14'%3E%3Cg fill='none' stroke='%23fff' stroke-linecap='round'%3E%3Cpath stroke-width='0.9' d='M145.3 6.5L146.2 13.5M271.4 8.0L271.3 13.5M337.2 8.0L337.2 13.5M366.5 6.7L366.2 13.5M527.9 7.7L528.4 13.5'/%3E%3Cpath stroke-width='1.0' d='M62.2 6.4L61.9 13.5M81.0 6.6L81.7 13.5M178.0 7.7L177.9 13.5M625.7 6.6L626.3 13.5'/%3E%3Cpath stroke-width='1.1' d='M14.1 7.5L13.7 13.5M47.8 7.6L48.5 13.5M111.6 8.1L112.5 13.5M239.7 7.2L240.8 13.5M254.5 7.3L254.0 13.5M414.0 7.3L413.2 13.5M606.2 7.8L606.7 13.5M642.2 7.7L642.8 13.5M705.0 6.4L705.6 13.5'/%3E%3Cpath stroke-width='1.2' d='M32.4 6.9L32.1 13.5M126.5 6.7L127.2 13.5M206.5 8.2L207.1 13.5M223.5 7.7L224.6 13.5M354.2 6.9L353.7 13.5M433.0 6.5L433.9 13.5M497.0 7.2L497.3 13.5M511.8 6.6L512.4 13.5'/%3E%3Cpath stroke-width='1.3' d='M159.8 6.9L159.8 13.5M303.2 6.5L303.1 13.5M319.6 7.8L320.6 13.5M400.7 8.0L401.4 13.5M446.4 6.9L445.7 13.5M462.4 7.9L462.1 13.5M544.0 7.4L544.3 13.5M558.8 6.9L559.2 13.5M594.0 6.6L593.3 13.5M656.1 7.0L657.0 13.5M686.0 6.6L685.5 13.5'/%3E%3C/g%3E%3C/svg%3E");
}

.axis__marker {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
  margin-inline-start: calc(var(--mark, 0%) * var(--mark-scale));
}

.axis__tick {
  display: block;
  inline-size: 2px;
  block-size: 22px;
  background-color: var(--moss);
}

/* Fredoka carries the character; the tracking stays close to normal so the
   labels read as signage rather than as science-fiction interface text. */
.axis__label {
  font-family: 'Fredoka', 'Trebuchet MS', 'Segoe UI', sans-serif;
  font-weight: 600;
  font-size: var(--text-sm);
  line-height: 1.2;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--moss);
}

/* Positions along the range. */
#section-event      { --mark: 20%; }
#section-swing      { --mark: 42%; }
#section-simulation { --mark: 63%; }
#section-status     { --mark: 82%; }

/* The terminal marker sits flush against the right-hand end of the range.
   Aligned to the end of the axis rather than pushed with a 100% margin, which
   would leave the tick no room and overflow the container. */
.axis--terminus .axis__marker {
  align-self: flex-end;
}

.axis--terminus .axis__tick {
  block-size: 14px;
}

/* --------------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------------- */

.hero {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* The render and the subtitle are one mark, not two stacked elements, so the
   gap between them stays tighter than any other vertical space on the page. */
.lockup {
  display: flex;
  flex-direction: column;
  gap: clamp(0.4rem, 0.2rem + 0.8vw, 0.9rem);
  font-weight: 400;
}

/* Mobile-first: fills the content frame, capped so it cannot dominate. The cap
   opens up at each desktop breakpoint. block-size stays auto and the
   width/height attributes carry the 1224x705 ratio, so the reserved box is
   correct before the file loads and the image can never be distorted.
   align-self is deliberate: .lockup is a column flex container, and the
   default `align-items: stretch` is what squashed the engine logo. */
.lockup__image {
  display: block;
  align-self: flex-start;
  inline-size: 100%;
  max-inline-size: 28rem;
  block-size: auto;
}

.lockup__title {
  font-family: 'Fredoka', 'Trebuchet MS', 'Segoe UI', sans-serif;
  font-weight: 400;
  font-size: var(--text-xl);
  line-height: 1.2;
  letter-spacing: 0.005em;
  color: var(--moss);
}

/* First of the two permitted --nugget appearances. */
.tagline {
  max-width: 26ch;
  font-size: var(--text-lg);
  font-weight: 600;
  line-height: 1.45;
  color: var(--nugget);
  text-wrap: balance;
}

/* --------------------------------------------------------------------------
   Status
   -------------------------------------------------------------------------- */

.status {
  font-family: 'Fredoka', 'Trebuchet MS', 'Segoe UI', sans-serif;
  font-weight: 500;
  font-size: var(--text-sm);
  line-height: 1.5;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--bone);
}

/* --------------------------------------------------------------------------
   Footer — a full-bleed dark band.

   The element spans the viewport so the band reaches both edges; its inner
   wrapper repeats the .page measurements so the content stays on the same
   grid as everything above it. The opaque background covers the body pattern.
   -------------------------------------------------------------------------- */

.footer {
  background-color: var(--pitch);
  padding-block: clamp(3rem, 2rem + 4vw, 5.5rem);
}

.footer__inner {
  width: min(100% - (var(--gutter) * 2), var(--page-max));
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.colophon {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--text-muted);
}

.colophon__studio {
  color: var(--bone);
  font-weight: 600;
}

.colophon__legal {
  font-size: var(--text-xs);
}

/* The engine credit: the mark sits with the copyright line it belongs to, and
   nothing else. No wording of our own accompanies it. */
.colophon__engine {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* `flex: none` is load-bearing. As a flex item the logo would otherwise shrink
   along the main axis while its height stayed fixed, distorting it — the same
   failure `align-items: stretch` caused when it lived in the prose column.
   The width/height attributes supply the ratio, so the box is reserved before
   the file loads. */
.engine-logo {
  flex: none;
  display: block;
  block-size: clamp(1.25rem, 1.05rem + 0.7vw, 1.6rem);
  inline-size: auto;
  max-inline-size: 100%;
}

/* inline-flex with a 44px minimum so the one real link on the page is a
   comfortable touch target on mobile. */
.link {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
  color: var(--bone);
  text-decoration: underline;
  text-decoration-color: var(--rule);
  text-underline-offset: 0.22em;
  transition: text-decoration-color 160ms ease;
}

/* Second and last of the two permitted --nugget appearances. */
.link:hover {
  text-decoration-color: var(--nugget);
}

/* --------------------------------------------------------------------------
   Social channels

   The logo artwork is never inlined. Each icon is a CSS mask pointing at a
   same-origin file in assets/icons/, tinted with currentColor, so colour stays
   under CSS control and no third party is contacted.

   Every channel is disabled. The icons sit grey and dimmed to read as
   inactive, and take their own brand colour on hover and keyboard focus.
   -------------------------------------------------------------------------- */

.social {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Positioned so the tooltips can anchor to the row rather than to individual
   buttons. Anchoring to a button would push the tooltip for the right-hand
   icons past the viewport edge at 320px; anchoring to the row cannot. All
   five carry the same message, so nothing is lost by placing them alike. */
.social__list {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.social__control {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 2.75rem;
  block-size: 2.75rem;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background-color: transparent;
  cursor: pointer;
  text-decoration: none;
  transition: border-color 160ms ease, background-color 160ms ease;
}

.social__control:hover,
.social__control:focus-visible {
  border-color: var(--ash);
  background-color: var(--surface);
}

/* Default: grey and dimmed, so the row reads as inactive at a glance. */
.social__icon {
  display: block;
  inline-size: 1.25rem;
  block-size: 1.25rem;
  color: var(--ash);
  opacity: 0.55;
  background-color: currentColor;
  transition: color 160ms ease, opacity 160ms ease;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
  -webkit-mask-size: contain;
          mask-size: contain;
}

.social__control:hover .social__icon,
.social__control:focus-visible .social__icon {
  opacity: 1;
}

.social__icon--instagram {
  -webkit-mask-image: url("assets/icons/instagram.svg");
          mask-image: url("assets/icons/instagram.svg");
}

.social__icon--x {
  -webkit-mask-image: url("assets/icons/x.svg");
          mask-image: url("assets/icons/x.svg");
}

.social__icon--mastodon {
  -webkit-mask-image: url("assets/icons/mastodon.svg");
          mask-image: url("assets/icons/mastodon.svg");
}

.social__icon--youtube {
  -webkit-mask-image: url("assets/icons/youtube.svg");
          mask-image: url("assets/icons/youtube.svg");
}

.social__icon--discord {
  -webkit-mask-image: url("assets/icons/discord.svg");
          mask-image: url("assets/icons/discord.svg");
}

/* One colour declaration per icon. The mask is tinted with currentColor, so
   setting `color` is all that is needed. X's official mark is #000000, which
   is unusable on this band, so it takes white. */
.social__control:is(:hover, :focus-visible) .social__icon--instagram { color: var(--brand-instagram); }
.social__control:is(:hover, :focus-visible) .social__icon--x         { color: var(--brand-x); }
.social__control:is(:hover, :focus-visible) .social__icon--mastodon  { color: var(--brand-mastodon); }
.social__control:is(:hover, :focus-visible) .social__icon--youtube   { color: var(--brand-youtube); }
.social__control:is(:hover, :focus-visible) .social__icon--discord   { color: var(--brand-discord); }

/* Tooltip. Kept in the accessibility tree at all times — it is referenced by
   aria-describedby, and a target hidden with display:none or visibility:hidden
   is not reliably announced — so it is revealed with opacity alone. It is
   absolutely positioned and overlays what follows, so showing it never moves
   the layout. max-inline-size is bounded by the row, which keeps it inside the
   viewport at every width. */
.social__tooltip {
  position: absolute;
  inset-block-start: calc(100% + 0.5rem);
  inset-inline-start: 0;
  z-index: 2;
  inline-size: max-content;
  max-inline-size: min(34ch, 100%);
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--rule);
  border-radius: 3px;
  background-color: var(--bark);
  color: var(--bone);
  font-size: var(--text-sm);
  line-height: 1.45;
  opacity: 0;
  pointer-events: none;
  transition: opacity 140ms ease;
}

.social__control:hover + .social__tooltip,
.social__control:focus-visible + .social__tooltip,
.social__item.is-open .social__tooltip {
  opacity: 1;
}

/* --------------------------------------------------------------------------
   Focus and skip link
   -------------------------------------------------------------------------- */

:focus-visible {
  outline: 2px solid var(--moss);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: absolute;
  inset-inline-start: -100vw;
  inset-block-start: 0;
  z-index: 3;
  padding: var(--space-1) var(--space-2);
  background-color: var(--bark);
  color: var(--bone);
  font-size: var(--text-sm);
  text-decoration: underline;
}

.skip-link:focus {
  inset-inline-start: var(--space-1);
  inset-block-start: var(--space-1);
}

/* --------------------------------------------------------------------------
   Wider viewports — min-width only.

   The base rules above describe the mobile layout. Three things open up with
   available width: how far the section markers travel, how wide the text
   measure is allowed to grow, and whether the hero is centred. Everything else
   scales continuously via clamp() and needs no breakpoint at all.
   -------------------------------------------------------------------------- */

@media (min-width: 34em) {
  :root {
    --mark-scale: 0.7;
  }
}

/* Tablet and up: the hero centres and becomes the title card it is, and the
   measure takes the first of three steps. */
@media (min-width: 48em) {
  :root {
    --mark-scale: 1;
    --measure: 64ch;
  }

  .hero {
    align-items: center;
    text-align: center;
  }

  .lockup {
    align-items: center;
  }

  .lockup__image {
    align-self: center;
    max-inline-size: 34rem;
  }

  .tagline {
    max-width: 34ch;
  }
}

/* Desktop: the prose column starts following its marker along the range, so
   the body of the page occupies the width rather than hugging the left edge. */
@media (min-width: 64em) {
  :root {
    --measure: 68ch;
    --cascade: 0.3;
  }

  .lockup__image {
    max-inline-size: 42rem;
  }
}

/* Large desktop: the frame itself widens. */
@media (min-width: 90em) {
  :root {
    --measure: 72ch;
    --page-max: 1200px;
  }

  .lockup__image {
    max-inline-size: 48rem;
  }
}

/* --------------------------------------------------------------------------
   Reduced motion — the page has no animation; this removes the hover and
   focus transitions as well. The background pattern is static in all cases.
   -------------------------------------------------------------------------- */

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