/* Stylesheet for lukotta.com.

   Layout: hairline rules rather than cards, no shadows, no gradients, set from
   the left.

   Colour is taken from the application and the brand rather than chosen:

     paper   #FBF8F2   the ground the light logo lockup sits on
     ink     #1F2127   the near-black of the dark lockup
     amber   #FF8D28   sampled from the drive icons and Locked badges in the
                       application's own interface

   Amber is too light to carry text on paper, so it is used for fills and
   marks; --amber-ink (#9A4E05) is used where a link must be read.

   Three typefaces:

     Plex Sans   headings. Covers Latin, Greek, Cyrillic and Vietnamese, which
                 is 30 of the 37 languages. The other 7 use their system face
                 at the same size and weight.
     Plex Mono   format names, section numbers, the specification line. All
                 ASCII, so only the Latin subset is needed.
     SF Pro      running text, via -apple-system, with Inter behind it for
                 platforms that are not Apple's.

   Plex and Inter are under the SIL Open Font License; see assets/fonts/. */

@font-face {
  font-family: "Plex Sans";
  font-style: normal;
  font-weight: 100 700;
  font-display: swap;
  src: url("assets/fonts/plex-sans-latin.woff2") format("woff2-variations");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: "Plex Sans";
  font-style: normal;
  font-weight: 100 700;
  font-display: swap;
  src: url("assets/fonts/plex-sans-latin-ext.woff2") format("woff2-variations");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: "Plex Sans";
  font-style: normal;
  font-weight: 100 700;
  font-display: swap;
  src: url("assets/fonts/plex-sans-vietnamese.woff2") format("woff2-variations");
  unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;
}
@font-face {
  font-family: "Plex Sans";
  font-style: normal;
  font-weight: 100 700;
  font-display: swap;
  src: url("assets/fonts/plex-sans-greek.woff2") format("woff2-variations");
  unicode-range: U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;
}
@font-face {
  font-family: "Plex Sans";
  font-style: normal;
  font-weight: 100 700;
  font-display: swap;
  src: url("assets/fonts/plex-sans-cyrillic.woff2") format("woff2-variations");
  unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;
}
@font-face {
  font-family: "Plex Sans";
  font-style: normal;
  font-weight: 100 700;
  font-display: swap;
  src: url("assets/fonts/plex-sans-cyrillic-ext.woff2") format("woff2-variations");
  unicode-range: U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F;
}
@font-face {
  font-family: "Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("assets/fonts/plex-mono-latin-400.woff2") format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: "Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("assets/fonts/plex-mono-latin-500.woff2") format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: "Inter Variable";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("assets/fonts/inter-latin.woff2") format("woff2-variations");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: "Inter Variable";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("assets/fonts/inter-latin-ext.woff2") format("woff2-variations");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: "Inter Variable";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("assets/fonts/inter-vietnamese.woff2") format("woff2-variations");
  unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;
}
@font-face {
  font-family: "Inter Variable";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("assets/fonts/inter-greek.woff2") format("woff2-variations");
  unicode-range: U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;
}
@font-face {
  font-family: "Inter Variable";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("assets/fonts/inter-greek-ext.woff2") format("woff2-variations");
  unicode-range: U+1F00-1FFF;
}
@font-face {
  font-family: "Inter Variable";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("assets/fonts/inter-cyrillic.woff2") format("woff2-variations");
  unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;
}
@font-face {
  font-family: "Inter Variable";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("assets/fonts/inter-cyrillic-ext.woff2") format("woff2-variations");
  unicode-range: U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F;
}

/* ---------------------------------------------------------------- tokens -- */

:root {
  color-scheme: light;

  --paper:       #FBF8F2;
  --paper-2:     #F4F0E5;
  --paper-3:     #EDE7D9;

  --ink:         #1F2127;
  --ink-2:       #575B64;
  --ink-3:       #6A6D74;

  --rule:        #E3DDCE;
  --rule-2:      #CFC8B4;
  --control-edge: #958E7A;

  --amber:       #FF8D28;
  --amber-ink:   #9A4E05;
  --on-amber:    #1F1608;

  --titlebar:    #ECECEC;
  --titlebar-edge: #D6D3CD;

  --tick:        #1B9E38;

  /* Which way round the appearance-specific pieces sit. Dark overrides them. */
  --sun-o: 0;   --moon-o: 1;
  --knob-x: 2px; --knob-bg: var(--ink);
  --shot-light-o: 1; --shot-dark-o: 0;

  --font-display: "Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
                  Roboto, "Noto Sans", "Nirmala UI", "Leelawadee UI",
                  "Microsoft YaHei", "Yu Gothic UI", "Malgun Gothic", sans-serif;

  --font: -apple-system, BlinkMacSystemFont,
          "Inter Variable", Inter,
          "Segoe UI Variable Text", "Segoe UI",
          Roboto, "Noto Sans",
          "Nirmala UI", "Leelawadee UI",
          "Microsoft YaHei", "PingFang SC",
          "Yu Gothic UI", Meiryo, "Malgun Gothic",
          "Helvetica Neue", Arial, sans-serif;

  --font-mono: "Plex Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo,
               Consolas, monospace;

  --page:   1120px;
  --gutter: clamp(20px, 5vw, 56px);
  --measure: 64ch;
}

/* The dark appearance is written twice on purpose. The media query serves a
   reader whose system asks for dark and whose JavaScript never ran; the
   attribute serves a reader who chose, and outranks the system either way.
   check.mjs compares the two blocks token by token, so they cannot drift. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --paper:       #15161A;
    --paper-2:     #1C1E23;
    --paper-3:     #23262C;

    --ink:         #F2EFE8;
    --ink-2:       #A6AAB3;
    --ink-3:       #82868F;

    --rule:        #2C2F36;
    --rule-2:      #40444D;
    --control-edge: #61656E;

    --amber:       #FF9230;
    --amber-ink:   #FFB061;
    --on-amber:    #16120A;

    --titlebar:    #2C2E33;
    --titlebar-edge: #3A3D44;

    --tick:        #3FD35F;

    --sun-o: 1;   --moon-o: 0;
    --knob-x: 23px; --knob-bg: var(--amber);
    --shot-light-o: 0; --shot-dark-o: 1;
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --paper:       #15161A;
  --paper-2:     #1C1E23;
  --paper-3:     #23262C;

  --ink:         #F2EFE8;
  --ink-2:       #A6AAB3;
  --ink-3:       #82868F;

  --rule:        #2C2F36;
  --rule-2:      #40444D;
  --control-edge: #61656E;

  --amber:       #FF9230;
  --amber-ink:   #FFB061;
  --on-amber:    #16120A;

  --titlebar:    #2C2E33;
  --titlebar-edge: #3A3D44;

  --tick:        #3FD35F;

  --sun-o: 1;   --moon-o: 0;
  --knob-x: 23px; --knob-bg: var(--amber);
  --shot-light-o: 0; --shot-dark-o: 1;
}

/* ------------------------------------------------------------------ base -- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 84px;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

h1 {
  font-size: clamp(2.35rem, 1.3rem + 4.2vw, 4rem);
  letter-spacing: -0.035em;
  line-height: 1.04;
  max-width: 17ch;
}

h2 { font-size: clamp(1.55rem, 1.2rem + 1.5vw, 2.15rem); }
h3 { font-size: 1.0625rem; letter-spacing: -0.012em; }

p { margin: 0; text-wrap: pretty; }
ul, ol, dl { margin: 0; padding: 0; list-style: none; }

a { color: var(--amber-ink); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }

code {
  font-family: var(--font-mono);
  font-size: .9375em;
  font-weight: 500;
}

img { max-width: 100%; height: auto; display: block; }

/* WCAG 2.4.11 requires 3:1 against the page. --amber reaches only 2.18:1 on
   paper, so --amber-ink is used: 5.72:1 in the light theme, and in the dark
   theme it is the lighter token at 10:1. */
:focus-visible { outline: 2px solid var(--amber-ink); outline-offset: 3px; }

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

.skip-link {
  position: absolute; inset-inline-start: 12px; top: -100px; z-index: 200;
  padding: 10px 16px; background: var(--paper); color: var(--ink);
  border: 1px solid var(--rule-2); transition: top .15s ease;
}
.skip-link:focus { top: 12px; }

.wrap {
  width: 100%; max-width: var(--page);
  margin-inline: auto; padding-inline: var(--gutter);
}

/* --------------------------------------------------------------- header -- */

.site-header {
  position: sticky; top: 0; z-index: 100;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  -webkit-backdrop-filter: saturate(150%) blur(14px);
  backdrop-filter: saturate(150%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color .2s ease;
}
.site-header[data-scrolled="true"] { border-bottom-color: var(--rule); }

.header-inner {
  display: grid; align-items: center; gap: 14px; height: 62px;
  grid-template-columns: 1fr auto 1fr;
}

.brand {
  display: inline-flex; align-items: center; gap: 9px;
  color: var(--ink); justify-self: start;
  font-family: var(--font-display);
  font-weight: 600; font-size: 1.0625rem; letter-spacing: -0.02em;
}
.brand:hover { text-decoration: none; }
.brand img { width: 22px; height: 22px; }

.site-nav { display: flex; align-items: center; justify-content: center; gap: 26px; }
.site-nav a {
  color: var(--ink-2); font-size: .9375rem;
  padding-block: 4px;
  border-bottom: 1px solid transparent;
}
.site-nav a:hover {
  color: var(--ink); text-decoration: none;
  border-bottom-color: var(--amber);
}

.header-tools { display: flex; align-items: center; justify-content: flex-end; gap: 12px; }

/* Appearance: a two-state switch. */
/* The switch only means something once script.js can store a choice, so it is
   absent until the inline head script marks the document as scripted. The
   appearance still follows the system without it. */
.theme-switch { display: none; }
:root.js .theme-switch { display: revert; }

.theme-switch {
  position: relative; width: 46px; height: 25px; padding: 0;
  border: 1px solid var(--control-edge); border-radius: 999px;
  background: var(--paper-2); cursor: pointer;
}
.theme-switch .track {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: space-between;
  padding-inline: 5px;
}
.theme-switch .ico { display: grid; place-items: center; color: var(--ink-2); }
/* The knob covers one end, so only the far icon is shown. It indicates the
   appearance a click will move to. Which one shows is a token, so the rule is
   written once and both dark paths drive it. */
.theme-switch .ico-sun { opacity: var(--sun-o); }
.theme-switch .ico-moon { opacity: var(--moon-o); }
.theme-switch svg { width: 12px; height: 12px; }
.theme-switch .knob {
  position: absolute; top: 2px; inset-inline-start: var(--knob-x);
  width: 19px; height: 19px; border-radius: 50%;
  background: var(--knob-bg);
  transition: inset-inline-start .18s ease;
}

/* Language menu. */
.lang { position: relative; }
.lang > summary {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 9px; list-style: none; cursor: pointer;
  border: 1px solid var(--control-edge); border-radius: 4px;
  background: var(--paper-2); color: var(--ink-2);
  font-size: .8125rem;
}
.lang > summary::-webkit-details-marker { display: none; }
.lang > summary:hover { color: var(--ink); }
.lang > summary svg { width: 14px; height: 14px; flex: none; }

.lang-panel {
  position: absolute; inset-inline-end: 0; top: calc(100% + 8px); z-index: 120;
  width: min(560px, calc(100vw - 2 * var(--gutter)));
  max-height: min(66vh, 520px); overflow-y: auto;
  padding: 8px;
  background: var(--paper); border: 1px solid var(--rule-2);
}
.lang-list { display: grid; gap: 0; grid-template-columns: repeat(auto-fill, minmax(158px, 1fr)); }
.lang-list a {
  display: block; padding: 6px 9px; color: var(--ink-2); font-size: .875rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lang-list a:hover { background: var(--paper-2); color: var(--ink); text-decoration: none; }
.lang-list a[aria-current="true"] { color: var(--ink); font-weight: 600; }
.lang-list a[aria-current="true"]::before { content: "› "; color: var(--amber-ink); }

/* --------------------------------------------------------------- pieces -- */

.btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 11px 20px; border-radius: 5px;
  background: var(--amber); color: var(--on-amber);
  font-weight: 550; font-size: 1rem; letter-spacing: -0.01em;
}
.btn:hover { text-decoration: none; background: color-mix(in srgb, var(--amber) 86%, black); }

/* Underlined to read as a link. Without it, grey text beside an arrow reads
   as a caption. The rule is faint until hover. */
.plain {
  color: var(--ink-2); font-size: .9375rem;
  display: inline-flex; align-items: center; gap: 6px;
  text-decoration: underline;
  text-decoration-color: var(--border, var(--rule-2));
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}
.plain:hover { color: var(--amber-ink); text-decoration-color: currentColor; }
.plain .arrow { width: 14px; height: 14px; }

.spec {
  margin-top: 22px;
  font-family: var(--font-mono);
  font-size: .75rem; letter-spacing: .01em;
  color: var(--ink-3);
}

.lead { font-size: clamp(1.0625rem, 1rem + .4vw, 1.25rem); color: var(--ink-2); max-width: 52ch; }
.lead-in { color: var(--ink); }
.prose { max-width: var(--measure); display: grid; gap: 22px; color: var(--ink-2); }
.prose .lead-in { font-size: 1.0625rem; }

.hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 26px; margin-top: 32px; }

/* The Homebrew line, under the download button. The command is a shell command
   in every language, so it is held left-to-right whatever the page direction,
   and it never wraps: a broken command line is one that will not paste. */
.brew { margin-top: 28px; max-width: 34rem; }
.brew-line {
  display: flex; align-items: stretch;
  border: 1px solid var(--rule-2); border-radius: 6px;
  background: var(--paper-2);
  overflow: hidden;
}
.brew-cmd {
  flex: 1 1 auto; min-width: 0;
  direction: ltr; text-align: left;
  padding: 11px 14px;
  overflow-x: auto; white-space: nowrap;
  font-family: var(--font-mono); font-size: .8125rem; color: var(--ink);
}
.brew-copy {
  flex: none; padding: 0 15px;
  border: 0; border-inline-start: 1px solid var(--rule-2);
  background: transparent; color: var(--ink-2);
  font-family: var(--font-mono); font-size: .75rem; font-weight: 500;
  letter-spacing: .06em; text-transform: uppercase;
  cursor: pointer; transition: background-color .15s ease, color .15s ease;
}
.brew-copy:hover { background: var(--paper-3); color: var(--ink); }
.brew-copy[data-copied="true"] { color: var(--tick); }

/* ----------------------------------------------------------------- hero -- */

.hero { padding-block: clamp(52px, 8vw, 96px) clamp(40px, 6vw, 72px); }
.hero-text { max-width: 62ch; }
.hero h1 { margin-bottom: 24px; }
/* A macOS window at the measurements macOS uses: 28pt title bar, 12pt buttons
   8pt apart, 20pt from the leading edge, 10pt corner. Nothing is added: no
   title, no toolbar. The application draws its own header inside the image.

   macOS corners are continuous rather than circular, which border-radius
   cannot express. At 10pt the difference is under a pixel. */
.shot {
  /* The captures are 1160px wide and shown at 720, which is 1.6x density.
     build.mjs warns if a capture is ever narrower than this. */
  max-width: 720px;
  margin: clamp(44px, 6vw, 76px) 0 0;
  border: 1px solid var(--titlebar-edge);
  border-radius: 10px;
  overflow: hidden;                 /* clips the image to the corner radius */
  background: var(--titlebar);
}
.shot-bar {
  display: flex; align-items: center; gap: 8px;
  height: 28px; padding-inline: 20px;
  background: var(--titlebar);
  border-bottom: 1px solid var(--titlebar-edge);
}
.shot-bar i {
  width: 12px; height: 12px; border-radius: 50%; display: block;
  box-shadow: inset 0 0 0 .5px rgba(0, 0, 0, .14);
}
.shot-bar .close    { background: #FF5F57; }
.shot-bar .minimise { background: #FEBC2E; }
.shot-bar .zoom     { background: #28C840; }
/* The two appearances are stacked. The light one is in flow and sets the
   height; the dark one sits on top of it and their opacities cross-fade. Which
   is shown follows the appearance tokens, so it agrees with the page whether
   the appearance came from data-theme or from prefers-color-scheme.

   The captures are 1160px wide and shown at 720, which is 1.6x density. */
.shot-frame { position: relative; }
.shot-img {
  display: block; width: 100%;
  transition: opacity .35s ease;
}
.shot-light { opacity: var(--shot-light-o); }
.shot-dark { position: absolute; inset: 0; opacity: var(--shot-dark-o); }

/* ------------------------------------------------------------- sections -- */

section.rule { padding-block: clamp(52px, 7vw, 88px); border-top: 1px solid var(--rule); }

.section-head {
  padding-bottom: 14px; margin-bottom: clamp(28px, 4vw, 44px);
  border-bottom: 1px solid var(--ink);
}

.sub {
  margin-top: clamp(44px, 6vw, 68px); padding-bottom: 10px;
  border-bottom: 1px solid var(--rule);
  font-family: var(--font-mono); font-size: .75rem; font-weight: 500;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3);
}

/* ---------------------------------------------------------------- table -- */

.table-scroll { overflow-x: auto; margin-top: 34px; }
table.formats { width: 100%; border-collapse: collapse; font-size: .9063rem; min-width: 620px; }

table.formats thead th {
  text-align: start; padding: 0 14px 9px 0;
  border-bottom: 1px solid var(--ink);
  font-family: var(--font-mono); font-weight: 500; font-size: .6875rem;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3);
}
table.formats thead th:last-child { padding-inline-end: 0; }

tr.group th {
  text-align: start;
  padding: 26px 0 8px;
  font-family: var(--font-mono); font-weight: 500; font-size: .6875rem;
  letter-spacing: .12em; text-transform: uppercase; color: var(--amber-ink);
  border-bottom: 1px solid var(--rule);
}
tbody tr:not(.group) th, tbody td {
  padding: 12px 14px 12px 0;
  border-bottom: 1px solid var(--rule);
  vertical-align: baseline;
}
tbody td:last-child { padding-inline-end: 0; }
tbody tr:not(.group) th { text-align: start; font-weight: 400; white-space: nowrap; }
tbody tr:not(.group) th code { color: var(--ink); }

.col-mark { width: 74px; }
.col-note { color: var(--ink-2); }
.mark { font-size: 1rem; line-height: 1; }
.mark.yes { color: var(--tick); font-weight: 700; }
.mark.no { color: var(--ink-3); }
/* A filled disc marks a row handled by macOS itself. The note in the same row
   states this in words. */
.mark.native {
  display: inline-block; vertical-align: middle;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--tick);
}

.asterisk { color: var(--amber-ink); margin-inline-start: 2px; }

/* Sits under the table it annotates, above the link to SPECS. No measure
   limit, so it stays on one line at desktop widths. */
.footnote {
  margin-top: 16px;
  color: var(--ink-3); font-size: .8438rem; line-height: 1.55;
}
.footnote span { color: var(--amber-ink); }

.after-table { margin-top: 22px; }

.aside {
  margin-top: clamp(40px, 5vw, 60px);
  padding: 20px 24px;
  background: var(--paper-2);
  border-inline-start: 2px solid var(--amber);
  max-width: var(--measure);
}
.aside h3 {
  font-family: var(--font-mono); font-size: .6875rem; font-weight: 500;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3);
  margin-bottom: 10px;
}
.aside p, .aside li { color: var(--ink-2); font-size: .9063rem; line-height: 1.6; }
.aside .bullets li {
  padding-block: 5px 5px;
  padding-inline-start: 18px;
  position: relative;
}
.aside .bullets li::before {
  content: "";
  position: absolute; inset-inline-start: 2px; top: .72em;
  width: 4px; height: 4px; border-radius: 50%;
  background: var(--amber);
}

/* ---------------------------------------------------------------- steps -- */

.steps { counter-reset: step; margin-top: 34px; display: grid; gap: 0; }
/* First element in the section, so no space above it. */
.steps-first { margin-top: 0; }
.steps-first li:first-child { padding-top: 0; }
.after-steps { margin-top: 30px; }
.steps li {
  counter-increment: step;
  display: grid; grid-template-columns: 3.2rem 1fr; gap: 4px 8px;
  padding-block: 20px; border-bottom: 1px solid var(--rule);
}
.steps li::before {
  content: counter(step, decimal-leading-zero);
  grid-row: 1 / span 2;
  font-family: var(--font-mono); font-size: .75rem; font-weight: 500;
  letter-spacing: .1em; color: var(--amber-ink); padding-top: 4px;
}
.steps h3 { margin-bottom: 5px; }
.steps p { color: var(--ink-2); font-size: .9375rem; max-width: 58ch; }

/* --------------------------------------------------------------- footer -- */

.site-footer { padding-block: 40px 48px; border-top: 1px solid var(--ink); }
.site-footer nav { display: flex; flex-wrap: wrap; gap: 26px; }
.site-footer nav a {
  color: var(--ink); font-size: .9375rem;
  text-decoration: underline;
  text-decoration-color: var(--rule-2);
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}
.site-footer nav a:hover { color: var(--amber-ink); text-decoration-color: currentColor; }
.colophon {
  margin-top: 26px; display: grid; gap: 3px;
  color: var(--ink-3); font-size: .8438rem;
}
.colophon a { color: var(--ink-2); padding-block: 4px; }
/* A reversed copyright sign is a copyleft sign. Done with a transform rather
   than U+1F12F, which most fonts have no glyph for. */
.copyleft { display: inline-block; transform: scaleX(-1); }

/* ----------------------------------------------------------- responsive -- */

/* The language button's native-name label is what crowds the header. Dropping
   it first leaves room for the navigation on a tablet. */
@media (max-width: 900px) {
  .lang > summary span { display: none; }
}

/* Below this width the three links no longer fit beside the brand and the
   controls, so the header becomes two rows: brand and controls above, links
   below. The links stay visible, and no JavaScript or disclosure is involved. */
@media (max-width: 620px) {
  .header-inner {
    height: auto; padding-block: 10px;
    grid-template-columns: 1fr auto;
    grid-template-areas: "brand tools" "nav nav";
    row-gap: 12px;
  }
  .brand { grid-area: brand; }
  .header-tools { grid-area: tools; }
  .site-nav { grid-area: nav; justify-content: center; gap: 20px; flex-wrap: wrap; }
  .site-nav a { font-size: .875rem; }
  html { scroll-padding-top: 112px; }
}

/* The specification line holds one line. In the monospace face the longest of
   the thirty-seven translations measures 470px, and the gutter is 5vw here, so
   the monospace stops fitting below a 529px screen; keeping it would need
   8.5px to fit a 375px screen, which cannot be read. The sans face is narrow
   enough to hold the line at a size that can. The switch is set above the
   measured crossover rather than at it, so a longer version number does not
   put the line back on two. */
@media (max-width: 560px) {
  .spec {
    font-family: var(--font-display);
    letter-spacing: 0;
    white-space: nowrap;
    /* The longest translation is a shade under 30 times its own font size, so
       dividing the line box by 31 keeps every language on one line with a
       little to spare. Capped at 11px, and floored so it never shrinks past
       reading size on a very narrow phone. */
    font-size: clamp(.5625rem, calc((100vw - 2 * var(--gutter)) / 31), .6875rem);
  }
}

@media (max-width: 560px) {
  /* The command needs the whole width here, so the button goes under it, and
     the type follows the width of the box so the line never has to scroll: a
     command you have to drag sideways to read is a command you mistype. The
     divisor is the command's width in multiples of its own font size, with a
     little to spare. */
  .brew-line { display: block; }
  .brew-cmd {
    display: block; padding: 10px 12px;
    font-size: clamp(.5625rem, calc((100vw - 2 * var(--gutter) - 26px) / 28), .8125rem);
  }
  .brew-copy {
    display: block; width: 100%;
    padding: 9px 0; text-align: center;
    border-inline-start: 0; border-top: 1px solid var(--rule-2);
  }
}

@media (max-width: 560px) {
  body { font-size: 16px; }
  .steps li { grid-template-columns: 2.4rem 1fr; }
}

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

@media print {
  /* Paper is white whatever the reader was looking at. Without this a dark
     page prints its near-white ink onto a background the browser drops. */
  :root, :root[data-theme="dark"], :root:not([data-theme="light"]) {
    color-scheme: light;
    --paper: #FFFFFF; --paper-2: #FFFFFF; --paper-3: #FFFFFF;
    --ink: #000000;   --ink-2: #222222;   --ink-3: #444444;
    --rule: #BBBBBB;  --rule-2: #999999;  --control-edge: #888888;
    --amber: #A05000; --amber-ink: #7A3E00; --on-amber: #000000;
    --titlebar: #F2F2F2; --titlebar-edge: #CCCCCC; --tick: #10662A;
    --shot-light-o: 1; --shot-dark-o: 0;
  }
  body { background: #FFFFFF; color: #000000; }
  .site-header, .theme-switch, .lang { display: none; }
  a { color: inherit; }
  /* A URL the reader cannot click is worth spelling out. */
  .prose a[href^="http"]::after { content: " (" attr(href) ")"; font-size: .85em; word-break: break-all; }
  section.rule, .faq details { break-inside: avoid; }
  .faq details { border-bottom: 1px solid #BBBBBB; }
  /* A closed <details> cannot be opened from CSS: the browser skips rendering
     its contents and display has no say. script.js opens them for printing. */
}

/* ------------------------------------------------------------------ faq -- */

.faq { max-width: 74ch; }
.faq details { border-bottom: 1px solid var(--rule); }
.faq summary {
  display: flex; align-items: flex-start; gap: 16px;
  padding-block: 17px; cursor: pointer; list-style: none;
  font-family: var(--font-display);
  font-weight: 550; font-size: 1.0313rem; letter-spacing: -0.012em;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; flex: none; margin-inline-start: auto; margin-top: 7px;
  width: 8px; height: 8px;
  border-inline-end: 1.5px solid var(--amber-ink);
  border-block-end: 1.5px solid var(--amber-ink);
  transform: rotate(45deg); transition: transform .18s ease;
}
.faq details[open] summary::after { transform: rotate(-135deg); margin-top: 10px; }
.faq summary:hover { color: var(--amber-ink); }
.faq .answer {
  padding-bottom: 20px; color: var(--ink-2); font-size: .9375rem; max-width: 66ch;
  display: grid; gap: 16px;      /* exceeds the 1.55 leading, so breaks register */
}

/* macOS does not mirror the window buttons in right-to-left locales, so the
   drawn frame must not either. The screenshot inside it is localised. */
.shot-bar { direction: ltr; }

[dir="rtl"] .faq summary::after { transform: rotate(135deg); }
[dir="rtl"] .faq details[open] summary::after { transform: rotate(-45deg); }

/* --------------------------------------------------------------- notice -- */

/* Opened when a visitor who is not on a Mac presses Download. It states what
   the application requires; it does not block the download. */
.notice {
  width: min(440px, calc(100vw - 32px));
  padding: 26px 26px 22px;
  border: 1px solid var(--rule-2);
  border-radius: 10px;
  background: var(--paper);
  color: var(--ink);
}
.notice::backdrop { background: rgba(0, 0, 0, .45); }
.notice h2 {
  font-size: 1.25rem; letter-spacing: -0.02em;
  margin-bottom: 14px; max-width: none;
}
.notice p { color: var(--ink-2); font-size: .9375rem; line-height: 1.6; }
.notice .notice-hint { margin-top: 14px; }
.notice .notice-hint:empty { display: none; }

.notice-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin-top: 24px;
}
.notice-actions .btn { padding: 10px 18px; font-size: .9375rem; }

.btn-quiet {
  padding: 10px 16px; border-radius: 5px;
  border: 1px solid var(--control-edge); background: transparent;
  color: var(--ink); font: inherit; font-size: .9375rem; cursor: pointer;
}
.btn-quiet:hover { background: var(--paper-2); }

.plain-btn {
  margin-inline-start: auto;
  padding: 10px 4px; border: 0; background: none;
  color: var(--ink-3); font: inherit; font-size: .9375rem; cursor: pointer;
}
.plain-btn:hover { color: var(--ink); }

@media (max-width: 460px) {
  .notice-actions { flex-direction: column; align-items: stretch; }
  .notice-actions .btn, .btn-quiet { width: 100%; text-align: center; justify-content: center; }
  .plain-btn { margin-inline-start: 0; }
}


/* ------------------------------------------------------ appearance change -- */

/* The colour change is animated, but only while it is happening. A permanent
   transition on these properties would also slow every hover, which has its
   own shorter timing. script.js sets this class for the length of the fade.

   opacity is in the list because this shorthand replaces any other transition
   while the class is set, and without it the screenshots would snap rather
   than cross-fade. */
:root.theme-changing,
:root.theme-changing *,
:root.theme-changing *::before,
:root.theme-changing *::after {
  transition: background-color .35s ease,
              color .35s ease,
              border-color .35s ease,
              fill .35s ease,
              opacity .35s ease !important;
}

@media (prefers-reduced-motion: reduce) {
  :root.theme-changing,
  :root.theme-changing *,
  :root.theme-changing *::before,
  :root.theme-changing *::after { transition: none !important; }
  .shot-img { transition: none; }
}
