/*
 * This is a manifest file that'll be compiled into application.css.
 *
 * With Propshaft, assets are served efficiently without preprocessing steps. You can still include
 * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
 * cascading order, meaning styles declared later in the document or manifest will override earlier ones,
 * depending on specificity.
 *
 * Consider organizing styles into separate files for maintainability.
 */

/* Every colour, type and radius token lives in tokens.css. */

/* The app follows the reader's OS theme. Telling the browser means native
   scrollbars, selects, date pickers and form autofill follow it too, instead
   of staying light against a dark page or vice versa. */
:root {
  color-scheme: light dark;
}

/* Reset and base styles */
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* Anchors and keyboard-scrolled elements land below the fixed navbar rather
   than underneath it. */
/* No scroll-behavior: smooth here. It animates every programmatic
   scrollIntoView too, so anything that scrolls and then measures or hovers acts
   on a position the page is still moving away from. */
html {
  scroll-padding-top: calc(var(--navbar-height) + 1rem);
}

/* One visible focus ring for everything, drawn only for keyboard focus.
   Components are free to add their own accent border on :focus for the mouse
   case; the ring is what guarantees a keyboard user can always see where they
   are. */
:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring);
  outline-offset: var(--focus-ring-offset);
  border-radius: 4px;
}

/* Clicking a control should not leave a ring behind it. */
:focus:not(:focus-visible) {
  outline: none;
}

/* Removes the 300ms double-tap-to-zoom delay on every control, and replaces
   the grey flash Android paints on tap with our own hover colour. */
a,
button,
input,
select,
textarea,
summary,
label,
[role="button"] {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

/* Something has to answer a press. The rule above turns off the grey flash
   Android paints on tap, and a phone has no hover to replace it with, so every
   control dips for as long as it is held. Components with a pressed state of
   their own -- the buttons that nudge down a pixel -- keep it and take this as
   well. */
a:active,
button:not(:disabled):active,
summary:active,
[role="button"]:active {
  opacity: 0.6;
}

/* Headings break across lines evenly instead of dropping a single word onto
   the last line. */
h1,
h2,
h3,
h4 {
  text-wrap: balance;
}

/* Body copy avoids widows too, and long unbroken strings (URLs, feed titles)
   wrap instead of forcing a horizontal scrollbar. */
p {
  text-wrap: pretty;
  overflow-wrap: break-word;
}

/* Quantities -- counts, durations, dates, delivery times -- are set in the
   data face. These are the same elements that already wanted tabular figures,
   so the mono is making an existing instinct visible rather than decorating. */
.follow-count,
.reaction-count,
.char-counter,
.article-date,
.publish-date,
time {
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

/* Anyone who has asked their OS to reduce motion gets the end state of every
   animation immediately, rather than the journey to it. Kept as one rule so a
   new component cannot forget to opt in. */
@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;
  }
}

/* Text for screen readers only. Used where state is carried visually by an
   icon or a colour, which an aria-hidden glyph cannot announce on its own. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Skip link. Off-screen until focused, then the first thing a keyboard user
   lands on -- so the nav does not have to be tabbed through on every page. */
.skip-link {
  position: absolute;
  left: 50%;
  top: 0;
  transform: translate(-50%, -100%);
  z-index: 2000;
  padding: 12px 20px;
  background-color: var(--bg-secondary);
  color: var(--text-primary);
  border: 1px solid var(--border-secondary);
  border-radius: 0 0 6px 6px;
  text-decoration: none;
  font-weight: 500;
  transition: transform 0.15s ease-out;
}

.skip-link:focus-visible {
  transform: translate(-50%, 0);
}

/* The display face is the default because most of the app is interface. Only
   reading surfaces -- article bodies, TL;DRs -- opt into the serif. */
body {
  font-family: var(--font-display);
  font-size: var(--fs-base);
  line-height: 1.65;
  color: var(--ink);
  background-color: var(--ground);
  padding: 0;
  padding-top: var(--navbar-height);
}

/* Navbar */
.navbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  background-color: var(--bg-secondary);
  border-bottom: 1px solid var(--border-primary);
  box-shadow: 0 1px 3px var(--shadow-light);
  z-index: 1000;
}

/* Three zones. The brand and the account button hold their width and only the
   pages between them give ground -- and past 640px they stop trying, because a
   nav row that shrinks to fit is a nav row that eventually clips whatever is
   beside it. That is how Kindle, and then the account button with it, went off
   the right edge of a phone and took Settings and Logout with them.

   The insets are the right way round now: the shorthand is top/right/bottom/left,
   so the old rule was padding the right edge by the *left* inset. */
.navbar-container {
  padding: 0 max(20px, env(safe-area-inset-right)) 0 max(20px, env(safe-area-inset-left));
  display: flex;
  align-items: center;
  gap: 15px;
  height: var(--navbar-height);
}

.navbar-brand {
  flex: 0 0 auto;
}

.navbar-brand .brand-link {
  font-size: 1.3em;
  font-weight: 600;
  color: var(--text-primary);
  text-decoration: none;
  transition: color 0.2s;
  display: flex;
  align-items: center;
}

.navbar-brand .brand-link:hover {
  color: var(--accent-hover);
}

/* <picture> is inline by default, which leaves a baseline gap under the mark
   and puts the bar's centring a pixel out. */
.navbar-brand picture {
  display: flex;
}

.navbar-logo {
  height: 30px;
  width: auto;
  display: block;
  margin: 0;
  padding: 0;
}

/* The pages as a row. Hidden on a phone, where .navbar-menu carries them. */
.navbar-links {
  display: flex;
  gap: 20px;
  flex: 1 1 auto;
  min-width: 0;
}

.nav-link {
  color: var(--text-muted);
  text-decoration: none;
  font-weight: 500;
  transition: color 0.2s;
}

.nav-link:hover {
  color: var(--accent-hover);
}

/* The page you are on. An underline as well as a colour, so the state is not
   carried by hue alone. */
.nav-link--current {
  color: var(--text-primary);
  box-shadow: inset 0 -2px 0 var(--accent-primary);
}

.navbar-links .nav-link {
  white-space: nowrap;
}

/* The same pages, behind one button, on screens that cannot hold the row. It
   takes the middle of the bar, between the mark and the account button -- see
   the 640px block, which is the only place it is ever shown. */
.navbar-menu {
  position: relative;
  display: none;
  flex: 0 0 auto;
}

.navbar-menu-trigger {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 50%;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background-color 0.2s;
}

.navbar-menu-trigger:hover {
  background-color: var(--bg-tertiary);
}

.navbar-menu-trigger:active {
  background-color: var(--sunk);
}

/* Held open. Driven by the attribute the dropdown controller already keeps
   correct, so the button cannot look shut while its menu is on screen. */
.navbar-menu-trigger[aria-expanded="true"] {
  background-color: var(--sunk);
  color: var(--ink);
}

.navbar-menu-icon {
  width: 24px;
  height: 24px;
}

.navbar-menu-panel {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  min-width: 200px;
  padding: 6px 0;
  background-color: var(--bg-secondary);
  border: 1px solid var(--border-primary);
  border-radius: 8px;
  box-shadow: 0 4px 12px var(--shadow-medium);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px);
  transition: transform 0.2s ease, opacity 0.2s ease, visibility 0.2s ease;
  z-index: 1000;
}

.navbar-menu-panel.show {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.navbar-menu-panel .nav-link {
  display: block;
  padding: 12px 16px;
  color: var(--text-secondary);
}

.navbar-menu-panel .nav-link:hover {
  background-color: var(--bg-tertiary);
  color: var(--text-primary);
}

/* The accent moves to the left edge: an underline inside a stacked menu reads
   as a divider between two items rather than as a mark on one. */
.navbar-menu-panel .nav-link--current {
  color: var(--text-primary);
  box-shadow: inset 2px 0 0 var(--accent-primary);
}

/* Container */
.container {
  max-width: 1200px;
  margin: 20px auto;
  background-color: var(--bg-secondary);
  padding: 30px;
  border-radius: 8px;
  box-shadow: 0 2px 4px var(--shadow-light);
}

/* Typography */
h1,
h2,
h3 {
  font-family: var(--font-display);
  letter-spacing: -0.015em;
}

h1 {
  font-size: var(--fs-2xl);
  line-height: 1.1;
  margin-bottom: 30px;
  color: var(--text-primary);
}

h2 {
  font-size: var(--fs-xl);
  line-height: 1.2;
  margin-bottom: 10px;
  color: var(--text-primary);
}

h2 a {
  color: var(--text-primary);
  text-decoration: none;
  transition: color 0.2s;
}

h2 a:hover {
  color: var(--accent-hover);
}

h3 {
  font-size: var(--fs-md);
  line-height: 1.3;
  margin-bottom: 10px;
  color: var(--text-tertiary);
}

/* Responsive */
@media (max-width: 768px) {
  .container {
    margin: 10px;
    padding: 20px;
  }

  .navbar-container {
    padding: 0 max(14px, env(safe-area-inset-right)) 0 max(14px, env(safe-area-inset-left));
    gap: 12px;
  }

  .navbar-links {
    gap: 16px;
  }

  .navbar-brand .brand-link {
    font-size: 1.1em;
  }

  h1 {
    font-size: var(--fs-xl);
  }

  h2 {
    font-size: var(--fs-lg);
  }

  /* iOS Safari zooms the page whenever a focused field's text is under 16px,
     and does not zoom back out afterwards. Every field in the app sat at 15px,
     so tapping any of them left the reader at 1.2x with the layout off-screen.
     max() keeps the larger sizes any component has chosen for itself. */
  input:not([type="range"]):not([type="checkbox"]):not([type="radio"]),
  select,
  textarea {
    font-size: max(16px, 1em);
  }
}

/* The row gives way to the menu. 640px rather than 768: a tablet has room for
   the pages in the open and should keep them there. */
@media (max-width: 640px) {
  .navbar-container {
    position: relative;
  }

  .navbar-links {
    display: none;
  }

  /* Centred on the bar rather than parked next to the logo. The zones on
     either side are a 30px mark and a 44px button, so flex alone would put it
     off-centre by seven pixels -- close enough to look like a mistake. Taken
     out of the flow it sits on the middle of the bar exactly, and the logo and
     the account button keep their own edges. */
  .navbar-menu {
    display: block;
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
  }

  .navbar-menu-panel {
    left: 50%;
    transform: translateX(-50%) translateY(-10px);
    max-width: calc(100vw - 28px);
  }

  .navbar-menu-panel.show {
    transform: translateX(-50%) translateY(0);
  }
}