/* The Salish postcard on the web (ADR 0017, #502): type, layout and the page's parts, on the colours in tokens.css
   (generated from the app's asset catalog). Site/README.md says how the pieces fit. */

/* ── Type ─────────────────────────────────────────────────────────────── */

/* The app's own Bricolage Grotesque instances (OFL), subset by scripts/build-web-fonts.sh. */
@font-face {
  font-family: "Bricolage";
  src: url("../fonts/BricolageGrotesque-ExtraBold.woff2") format("woff2");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Bricolage";
  src: url("../fonts/BricolageGrotesque-Bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  /* The dusk sky (Kit/Scene/ScenePalette.swift's dusk), for art only: the scenes themselves are #503's. */
  --dusk-top: #3b2f4a;
  --dusk-sky: #c5776a;
  --on-dusk: #ffffff;
  /* White on the action band, whatever the scheme, as in the app's ActionBand. */
  --on-band: #ffffff;

  /* Names, times and headings in Bricolage; reading text in the system's face, as in the app. */
  --display: "Bricolage", system-ui, sans-serif;
  --body: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;

  /* A fluid scale. Reading sizes are in rem, so they follow the reader's text size (Dynamic Type on iPhone and iPad)
     all the way. Display sizes grow with the width, and by three quarters of what the reading text gains, as Apple's
     text styles do: a large title doesn't triple at the largest sizes. Page zoom scales both (WCAG 1.4.4). */
  --grow: calc((1rem - 16px) * 0.75);
  --step--1: clamp(0.875rem, 0.85rem + 0.1vw, 0.9375rem);
  --step-0: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  --step-1: clamp(1.1875rem, 1.1rem + 0.4vw, 1.375rem);
  --step-1-display: calc(clamp(19px, 17.6px + 0.4vw, 22px) + var(--grow));
  --step--1-display: calc(14px + var(--grow));
  --step-2: calc(clamp(23px, 20.3px + 0.8vw, 30px) + var(--grow));
  --step-3: calc(clamp(28px, 23.2px + 1.4vw, 42px) + var(--grow));
  --step-4: calc(clamp(34px, 25.6px + 2.4vw, 56px) + var(--grow));
  --step-5: calc(clamp(40px, 27.2px + 3.6vw, 76px) + var(--grow));

  --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;

  /* A readable line, and the widest a page's content runs; art can run past both. */
  --measure: 40rem;
  --page: 72rem;
  --gutter: 16px;
  --inset-left: max(var(--gutter), env(safe-area-inset-left));
  --inset-right: max(var(--gutter), env(safe-area-inset-right));

  --radius: 16px;
  --focus: var(--sound);
}

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

html {
  font-family: var(--body);
  font-size: 100%;
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* On iPhone and iPad the page follows the reader's text size (Dynamic Type), as the app does. */
@supports (font: -apple-system-body) and (-webkit-touch-callout: none) {
  html {
    font: -apple-system-body;
    font-family: var(--body);
    line-height: 1.5;
  }
}

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--mist);
  color: var(--ink);
  font-size: var(--step-0);
  /* The last resort: a word too long for the line breaks rather than push the page sideways (at the largest text on
     a phone, "Bainbridge" alone can be wider than the screen). */
  overflow-wrap: anywhere;
}

h1,
h2,
h3,
.display {
  font-family: var(--display);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

h1 {
  font-size: var(--step-4);
  margin: 0 0 var(--space-4);
}

h2 {
  font-size: var(--step-2);
  margin: var(--space-7) 0 var(--space-3);
}

h3 {
  font-size: var(--step-1-display);
  font-weight: 700;
  margin: var(--space-5) 0 var(--space-2);
}

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

.caption {
  color: var(--ink-2);
  font-size: var(--step--1);
}

/* Times line up, as the app's monospaced digits do. */
.time {
  font-family: var(--display);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

a {
  color: var(--sound);
  text-decoration-thickness: 0.08em;
  text-underline-offset: 0.18em;
}

a:hover {
  text-decoration-thickness: 0.14em;
}

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
}

img,
svg {
  max-width: 100%;
}

img {
  height: auto;
}

/* Hidden is hidden, whatever display a class gives it. */
[hidden] {
  display: none !important;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ── Layout ───────────────────────────────────────────────────────────── */

/* Content at the page's width, clear of the notch and the home indicator; .prose keeps to a readable line. */
.wrap {
  box-sizing: content-box;
  max-width: var(--page);
  margin-inline: auto;
  padding-left: var(--inset-left);
  padding-right: var(--inset-right);
}

.prose {
  max-width: var(--measure);
}

/* A page of prose lines up with the header, its lines kept to the measure. */
.wrap.prose {
  max-width: var(--page);
}

.wrap.prose > * {
  max-width: var(--measure);
}

.holding > * {
  margin-inline: auto;
}

.prose ul,
.prose ol {
  margin: var(--space-5) 0;
  padding-left: 1.25rem;
}

.prose li + li {
  margin-top: var(--space-3);
}

/* Art edge to edge, whatever wraps it. */
.bleed {
  width: 100%;
}

/* Things one under another, a space apart. */
.stack > * {
  margin-block: 0;
}

.stack > * + * {
  margin-block-start: var(--stack-space, var(--space-4));
}

/* Things side by side that wrap when they run out of room. */
.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
}

/* Side by side while each has --switch-at of room, and one under another when they don't, as the app's layouts stack
   (ViewThatFits) rather than shrink their words. */
.switch {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

.switch > * {
  flex-grow: 1;
  flex-basis: calc((var(--switch-at, 30rem) - 100%) * 999);
}

main {
  flex: 1;
  padding-block: var(--space-6) var(--space-7);
}

/* The skip link's landing: focus moves there, with nothing drawn round the whole page. */
main:focus-visible {
  outline: none;
}

/* ── The page's shell ─────────────────────────────────────────────────── */

.skip {
  position: absolute;
  left: var(--inset-left);
  top: max(var(--space-3), env(safe-area-inset-top));
  z-index: 1;
  padding: var(--space-2) var(--space-3);
  background: var(--ink);
  color: var(--mist);
  font-weight: 600;
  text-decoration: none;
  border-radius: 8px;
}

/* Out of sight until it has focus, however big the reader's text. */
.skip:not(:focus) {
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.site-header {
  padding-top: env(safe-area-inset-top);
}

.site-header .wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-5);
  padding-block: var(--space-3);
}

/* The wordmark at the display master's size: at 32 px tall, under 40, the name stands without the rail. */
.home-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

.home-link img {
  display: block;
  height: 32px;
  width: auto;
}

.site-nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-nav a {
  display: inline-block;
  padding: 10px var(--space-2);
  font-family: var(--display);
  font-weight: 700;
  color: var(--ink);
  text-decoration: none;
}

.site-nav a:hover,
.site-nav a[aria-current="page"] {
  text-decoration: underline;
  text-decoration-color: var(--sound);
}

.site-footer {
  padding-bottom: max(var(--space-6), env(safe-area-inset-bottom));
  text-align: center;
  font-size: var(--step--1);
  color: var(--ink-2);
}

.site-footer .badge {
  display: block;
  width: 72px;
  height: 72px;
  margin: 0 auto var(--space-4);
}

.site-footer nav ul {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0 var(--space-5);
  margin: 0 0 var(--space-3);
  padding: 0;
  list-style: none;
}

.site-footer nav a {
  display: inline-block;
  padding: 10px var(--space-1);
  font-weight: 600;
  color: var(--ink);
}

.site-footer p {
  margin: var(--space-1) 0;
}

/* ── The rail: the section divider and the loading indicator ──────────── */

/* Decoration: an <hr> already says "a break here", and its art is a background, so nothing reads it twice. */
hr.rail {
  display: block;
  width: min(100%, 20rem);
  aspect-ratio: 10 / 1;
  margin: var(--space-7) auto;
  border: 0;
  background: url("../wordmark/rail-light.svg") center / contain no-repeat;
}

/* Your boat sails the crossing while something loads, and back again: the boats are double-ended. With Reduce Motion it
   rests where the rail's own boat does. The boat is 160 of the track's 1200 units across, and as tall: it starts 40
   units in and sails 960, six of its own widths. */
.loading {
  position: relative;
  width: min(100%, 20rem);
  aspect-ratio: 10 / 1;
  background: url("../wordmark/rail-track-light.svg") center / contain no-repeat;
}

.loading-boat {
  position: absolute;
  top: 0;
  left: 3.333%;
  height: 100%;
  aspect-ratio: 4 / 3;
  background: url("../wordmark/rail-boat-light.svg") center / contain no-repeat;
  animation: sail 4s ease-in-out infinite alternate;
}

@keyframes sail {
  from {
    transform: translateX(0);
  }

  to {
    transform: translateX(600%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .loading-boat {
    animation: none;
    transform: translateX(360%);
  }
}

@media (prefers-color-scheme: dark) {
  hr.rail {
    background-image: url("../wordmark/rail-dark.svg");
  }

  .loading {
    background-image: url("../wordmark/rail-track-dark.svg");
  }

  .loading-boat {
    background-image: url("../wordmark/rail-boat-dark.svg");
  }
}

/* ── Parts ────────────────────────────────────────────────────────────── */

.card {
  background: var(--paper);
  border: 1px solid transparent;
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-4) var(--space-5);
}

/* A state as a tag (the app's StatusTag): always its words, and a symbol whenever the state is news, so it never rests
   on its colour. Squared off where it starts and round where it ends, like a luggage tag. */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  padding: 0.2em 0.65em 0.2em 0.5em;
  border: 1.5px solid transparent;
  border-radius: 6px 999px 999px 6px;
  font-family: var(--display);
  font-weight: 700;
  font-size: var(--step--1-display);
  line-height: 1.25;
  /* One line while there's room; at the largest text sizes it wraps rather than run off a phone. */
  max-width: 100%;
}

.tag svg {
  width: 1em;
  height: 1em;
  flex: none;
}

.tag-on-time {
  background: var(--tag-on-time-fill);
  color: var(--tag-on-time-text);
}

.tag-delayed {
  background: var(--tag-delayed-fill);
  color: var(--tag-delayed-text);
}

.tag-scheduled {
  background: var(--tag-scheduled-fill);
  color: var(--tag-scheduled-text);
}

.tag-cancelled {
  background: var(--tag-cancelled-fill);
  color: var(--tag-cancelled-text);
}

/* Cancelled's red not yet confirmed, and an extra boat (ADR 0023) in the accent: on Paper, with a dashed edge. */
.tag-might-be-cancelled,
.tag-unscheduled {
  background: var(--paper);
  border-style: dashed;
  border-color: currentcolor;
}

.tag-might-be-cancelled {
  color: var(--tag-cancelled-text);
}

.tag-unscheduled {
  color: var(--sound);
}

/* The one thing to do next (the app's ActionBand): Evergreen, or Trouble's red when the plan has failed, and its words
   always white. */
.band {
  background: var(--evergreen);
  color: var(--on-band);
  border: 1px solid transparent;
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  --focus: var(--on-band);
}

.band.trouble {
  background: var(--trouble-band);
}

.band a {
  color: inherit;
}

.band-lead {
  margin: 0;
  font-family: var(--display);
  font-weight: 800;
  font-size: var(--step-2);
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
}

.band-note {
  margin: var(--space-1) 0 0;
  font-size: var(--step--1);
}

/* ── The home page's hero (#503) ──────────────────────────────────────── */

/* The panorama west from Colman Dock, in the sky it has now: the words on the band's colour (postcards.css's
   .hero-<phase>, the same in both schemes, as the sky is), and under them the art, whose own flat sky runs into it. The
   words never meet the mountains: the hero grows instead. */
.hero {
  padding-top: env(safe-area-inset-top);
}

.hero a {
  color: inherit;
  font-weight: 600;
}

.hero-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-5);
  padding-block: var(--space-3);
}

.hero-mark {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

.hero-mark img {
  display: block;
  height: 32px;
  width: auto;
}

.hero-text {
  text-align: center;
  padding-block: clamp(var(--space-6), 7vh, var(--space-8)) var(--space-5);
}

.hero-eyebrow {
  margin: 0;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.hero h1 {
  max-width: 16ch;
  margin: var(--space-3) auto var(--space-4);
  font-size: var(--step-5);
}

.hero-sub {
  max-width: 36ch;
  margin: 0 auto var(--space-5);
  font-size: var(--step-1);
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-3) var(--space-5);
}

/* Not a button: there's nothing to press until the app is in the App Store. */
.hero-soon {
  margin: 0;
  padding: var(--space-2) var(--space-4);
  border: 1.5px solid currentcolor;
  border-radius: 999px;
  font-weight: 700;
}

.hero-actions a {
  display: inline-block;
  padding-block: 10px;
}

/* The land fills its box, cropped at the sides: the card's middle on a phone, Alki to Magnolia on a laptop, the cranes
   to the Needle on an ultrawide. */
.hero-art {
  display: block;
  width: 100%;
  height: clamp(16rem, 30vw, 34rem);
  margin-top: var(--space-5);
  object-fit: cover;
  object-position: 50% 100%;
}

/* ── The home page, until the landing page (#504) ─────────────────────── */

.holding {
  text-align: center;
}

.lede {
  font-size: var(--step-1);
}

/* ── Postcards (#503) ─────────────────────────────────────────────────── */

/* A postcard is an object on the page (the canvas's A): cream card stock, the art inset, its words underneath, and a
   slight lean. Its colours are the card's own, the same in both schemes. */
.postcard {
  --card-stock: #fbf8f2;
  --card-ink: #1e2a2b;
  --card-ink-2: #4e5b5c;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
}

.postcard-frame {
  position: relative;
  width: 100%;
  padding: 10px 10px 0;
  background: var(--card-stock);
  color: var(--card-ink);
  border-radius: 4px;
  box-shadow: 0 14px 30px rgb(10 12 24 / 0.22);
  transform: rotate(-0.8deg);
}

.postcards > li:nth-child(even) .postcard-frame {
  transform: rotate(0.7deg);
}

.postcard-art {
  aspect-ratio: 390 / 240;
  border-radius: 2px;
  overflow: hidden;
}

.postcard-art svg,
.postcard-art img,
.play-art svg {
  display: block;
  width: 100%;
  height: 100%;
}

.postcard-art svg.fresh,
.play-art svg.fresh {
  animation: develop 0.9s ease-out;
}

@keyframes develop {
  from {
    opacity: 0;
  }
}

.postcard figcaption {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 var(--space-2);
  padding: var(--space-3) 2px var(--space-3);
}

.postcard-name {
  font-family: var(--display);
  font-weight: 800;
  font-size: var(--step-1-display);
  line-height: 1.15;
}

.postcard-place {
  font-family: var(--display);
  font-weight: 700;
  color: var(--card-ink-2);
}

.postcard-now,
.postcard-note {
  flex-basis: 100%;
  font-size: var(--step--1);
  color: var(--card-ink-2);
}

.postcard-note:not([hidden]) {
  font-weight: 600;
  color: var(--card-ink);
}

.postcard-play {
  min-height: 44px;
  padding: 0 var(--space-4);
  border: 1.5px solid var(--sound);
  border-radius: 999px;
  background: var(--paper);
  color: var(--sound);
  font: inherit;
  font-family: var(--display);
  font-weight: 700;
  cursor: pointer;
}

.postcard-play:hover {
  background: var(--mist);
}

/* The flagship leads, larger, with the postmark on it as a stamp. */
.postcard.lead {
  max-width: 52rem;
  margin: var(--space-6) auto var(--space-7);
}

.postcard.lead .postcard-frame {
  padding: 16px 16px 0;
  transform: rotate(-1.5deg);
}

.postcard-stamp {
  position: absolute;
  top: -18px;
  right: 0;
  width: clamp(64px, 14%, 112px);
  height: auto;
  padding: 6px;
  background: var(--card-stock);
  border: 2px dashed #c8c1b4;
  transform: rotate(7deg);
  box-shadow: 0 6px 14px rgb(10 12 24 / 0.2);
}

.postcard-region h2 {
  margin-top: var(--space-7);
}

.postcards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr));
  gap: var(--space-6) var(--space-5);
  margin: var(--space-4) 0 0;
  padding: 0;
  list-style: none;
}

/* Play: the card large, and what to change. */
dialog.play {
  width: min(100% - 2 * var(--gutter), 48rem);
  max-height: calc(100dvh - 2 * var(--gutter));
  padding: var(--space-4) var(--space-4) var(--space-5);
  border: 0;
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  box-shadow: 0 30px 80px rgb(10 12 24 / 0.4);
}

dialog.play::backdrop {
  background: rgb(10 12 24 / 0.55);
}

.play-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}

.play-head h2 {
  margin: 0;
}

.play-art {
  aspect-ratio: 390 / 240;
  border-radius: 6px;
  overflow: hidden;
  background: var(--mist);
}

.play-note {
  min-height: 1.5em;
  margin: var(--space-2) 0;
  font-weight: 600;
}

.play-controls {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
  gap: var(--space-3) var(--space-4);
}

.play fieldset {
  margin: 0;
  padding: 0;
  border: 0;
}

.play legend {
  margin-bottom: var(--space-1);
  font-family: var(--display);
  font-weight: 700;
}

.play fieldset label,
.play-special {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 32px;
}

.play input[type="radio"],
.play input[type="checkbox"] {
  width: 1.1em;
  height: 1.1em;
  margin: 0;
  accent-color: var(--sound);
}

.play-special {
  margin-top: var(--space-3);
}

.play-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  margin-top: var(--space-4);
}

.play-close,
.play-actions button {
  min-height: 44px;
  padding: 0 var(--space-4);
  border: 1.5px solid var(--sound);
  border-radius: 999px;
  background: var(--paper);
  color: var(--sound);
  font: inherit;
  font-family: var(--display);
  font-weight: 700;
  cursor: pointer;
}

.play-actions button[aria-pressed="true"] {
  background: var(--sound);
  color: var(--paper);
}

@media (prefers-reduced-motion: reduce) {
  .postcard-art svg.fresh,
  .play-art svg.fresh {
    animation: none;
  }
}

/* ── Asked-for looks ──────────────────────────────────────────────────── */

/* Windows' contrast themes repaint every colour: the edges the fills stood for come back, in the theme's own. */
@media (forced-colors: active) {
  .card,
  .band,
  .tag {
    border-color: CanvasText;
  }

  .postcard-frame {
    border: 1px solid CanvasText;
  }

  .tag-might-be-cancelled,
  .tag-unscheduled {
    border-style: dashed;
  }

  :focus-visible {
    outline-color: Highlight;
  }
}

@media print {
  .skip,
  .site-nav,
  hr.rail,
  .loading {
    display: none;
  }
}
