/* elements.dev shared site chrome. Imported by page.css so every page
   gets it. Families that used to ship in @elements/style v1 and left
   the package (brand mark, footer, shell widths, feed rows,
   segmented control, link-more) are absorbed here,
   alongside the app's own shared pieces (kind chips, page hero,
   ElementsBadge). */

/* Per-kind chip color rules — applied wherever a kind label needs
   tinting (ContentItem's kind label, post byline, search palette,
   etc.). Class names follow the pattern `.kind--<key>` so consumers
   pass `kindClass="kind--bug"` and the visible kind tint resolves
   automatically. Hex values live in ./vars.css. */
.kind--discuss   { color: var(--kind-discuss);  }
.kind--show      { color: var(--kind-show);     }
.kind--ask       { color: var(--kind-ask);      }
.kind--announce  { color: var(--kind-announce); }
.kind--course    { color: var(--kind-course);   }
.kind--lesson    { color: var(--kind-lesson);   }
.kind--guide     { color: var(--kind-guide);    }
.kind--video     { color: var(--kind-video);    }
.kind--demo      { color: var(--kind-demo);     }
.kind--comment   { color: var(--kind-comment);  }
.kind--user      { color: var(--kind-user);     }
.kind--page      { color: var(--kind-page);     }
.kind--bug       { color: var(--kind-bug);      }
.kind--feature   { color: var(--kind-feature);  }
.kind--question  { color: var(--kind-question); }

/* ─── Page hero ────────────────────────────────────────────────────
   h1 + paragraph subtitle, one rule used by every top-level page
   (/feed, /install, /learn, /pricing, /account, ...). Canonical
   top-level h1: 48px desktop, 40px on phones — matches the home
   hero so navigating between pages shows a single page-title scale.
   Page-specific CSS only tweaks margins/width around this. */
.page-hero { margin-bottom: var(--space-6); }

.page-hero-title {
  font-family: var(--font-sans);
  font-weight: var(--weight-bold);
  font-size: var(--page-title);
  letter-spacing: -0.02em;
  line-height: 1;
  margin: 2rem 0 var(--space-4);
  color: var(--ink);
}

.page-hero-sub {
  font-family: var(--font-sans);
  font-size: var(--text-md);
  color: var(--ink-soft);
  line-height: var(--leading-body);
  margin: 0;
  max-width: 36rem;
}
.page-hero-sub code {
  font-family: var(--font-mono);
  font-size: 0.875em;
  background: var(--bg-panel);
  padding: 0.0625rem 0.375rem;
  border-radius: var(--radius-xs);
  color: var(--ink);
}

.page-hero-lede {
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  color: var(--ink-soft);
  line-height: 1.6;
  max-width: 34rem;
  margin: 0 0 var(--space-7);
}

@media (max-width: 640px) {
  .page-hero-title {
    font-size: 2.5rem;
    line-height: 1.1;
    margin-top: 1.5rem;
  }
}

/* ─── ElementsBadge — staff-author attribution mark ───────────────
   Lightweight outlined "ELEMENTS" pill rendered next to a byline
   when the author is an Elements staff member. --accent colors lock
   the brand association regardless of context. Sized via em so it
   tracks the surrounding byline scale. Single source of truth —
   restyles live in this rule. */
.elements-pill {
  display: inline-flex;
  align-items: center;
  margin-left: 0.4rem;
  padding: 2px 5px;
  border-radius: 3px;
  color: var(--accent-deep);
  background: var(--accent-soft);
  font-family: var(--font-sans);
  font-size: 0.625rem;
  font-weight: var(--weight-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1;
  white-space: nowrap;
  flex-shrink: 0;
  vertical-align: 1px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ─── Container widths ─────────────────────────────────────────────
   Named page-column widths the site's shells and footer align to.
   --container-form (the 640px form column) lives in ./vars.css. */
:root {
  --container-marketing: 820px;    /* landing / feed / courses column */
  --container-wide:     1080px;    /* footer content width */

  /* Canonical page-title size. Every landmark page h1 (feed, learn,
     install, pricing, account, auth, etc.) pulls from this one token so
     the scale stays uniform and is tuned in a single place. Desktop
     value; the mobile step-down lives on each title's own breakpoint. */
  --page-title: 4rem;
}

/* ─── Brand mark + lockup ──────────────────────────────────────────
   The Elements mark (rounded square + chevron SVG) and the
   mark-plus-wordmark lockup rendered by <Mark> / <Brand>. The mark is
   the logo, so it is pinned to the Elements blue rather than following
   --accent: it reads the same in light and dark, and does not shift when
   the accent moves. Sizing comes from explicit width/height so the SVG
   scales crisply. */
.mark {
  color: var(--elements-blue-500);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  flex-shrink: 0;
  width: 24px;
  height: 24px;
}
.mark svg { width: 100%; height: 100%; display: block; }

/* Kept so existing markup carrying is-sky keeps working; the base rule
   above now does the same thing. */
.mark.is-sky { color: var(--elements-blue-500); }

.mark.size-24 { width: 24px; height: 24px; }

/* Lockup — mark + "elements" wordmark, rendered as one link. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.1875rem;
  font-family: var(--font-sans);
  font-weight: var(--weight-bold);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  letter-spacing: -0.025em;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
  font-size: 15px;
}
.brand > .mark { width: 18px; height: 18px; }

/* ─── Shell (width-bounded page container) ─────────────────────────
   Centers page content at the marketing column width with the
   standard desktop gutter. */
.shell-marketing {
  max-width: var(--container-marketing);
  margin: 0 auto;
  padding: 0 var(--space-8);
}

/* Mobile: tighten the page-content gutter so it aligns with the
   topbar's brand mark instead of sitting deeper into the viewport. */
@media (max-width: 700px) {
  .shell-narrow,
  .shell-prose,
  .shell-marketing,
  .shell-wide {
    padding-left:  1.5rem;
    padding-right: 1.5rem;
  }
}

/* ─── Footer ───────────────────────────────────────────────────────
   The bar spans the full viewport (border + background edge-to-edge);
   the inner row constrains width so content aligns with page shells.

     <footer class='footer'>
       <div class='footer-inner'>
         <div class='left'>…</div>
         <div class='right'>…</div>
       </div>
     </footer>
*/
.footer {
  border-top: 1px solid var(--rule);
  background: var(--bg);
  font-family: var(--font-sans);
  font-size: 0.71875rem;
  color: var(--ink-dim);
}
.footer-inner {
  max-width: var(--container-wide);
  margin: 0 auto;
  padding: var(--space-6) var(--space-8);
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3-5);
  align-items: center;
}
.footer .left {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  color: var(--ink-soft);
}
.footer .right { display: flex; gap: var(--space-3-5); }
.footer a { color: var(--ink-soft); }
.footer a:hover { color: var(--ink); }

/* ─── Feed ─────────────────────────────────────────────────────────
   HN-style vertical feed. `.feed` is the list wrapper (/home,
   /u/<handle>, /feed, /issues); generic `.item` rows are the issues
   lists' row shape. Defaults are wrapped in :where() so page-level
   row classes (.issues-row, .feed-row) override them freely. */
.feed { margin-top: var(--space-2); }

:where(.feed > .item) {
  display: grid;
  grid-template-columns: 28px 1fr 16px;
  gap: 0.875rem;
  padding: 0.625rem 0;
  align-items: baseline;
  border-bottom: 1px solid var(--rule-soft);
}
:where(.feed > .item:last-child) { border-bottom: none; }

/* Hovering anywhere on a row underlines its title link, so the whole
   row reads as one click target. */
:where(.feed > .item:hover .title a) {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--ink-faint);
  text-underline-offset: 3px;
}

/* ─── Segmented control ────────────────────────────────────────────
   Bordered group of exclusive-choice buttons (platform / arch picker
   in the install block). The active segment gets the accent wash. */
.seg {
  display: inline-flex;
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg);
}

.seg > :where(button, a) {
  font-family: var(--font-sans);
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: var(--weight-bold);
  background: var(--bg);
  color: var(--ink-dim);
  border: none;
  height: auto;
  border-radius: 0;
  padding: var(--space-2) 0.625rem;
  cursor: pointer;
  /* Segments touch. Nothing the baseline gives sibling buttons may open a
     gap here, or the active wash stops short of the divider. */
  margin: 0;
  border-right: 1px solid var(--rule);
  text-decoration: none;
  transition:
    background var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}
.seg > :where(button, a):last-child { border-right: none; }
.seg > :where(button, a):hover:not(.is-active) {
  color: var(--ink-soft);
  background: var(--bg-soft);
}
.seg > :where(button, a).is-active,
.seg > :where(button, a)[aria-selected="true"] {
  background: var(--accent-soft);
  color: var(--accent-deep);
}
.seg > :where(button, a):focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: -2px;
}

/* Row of .seg groups (platform + arch). Scrolls horizontally on
   narrow viewports instead of wrapping. */
.seg-row {
  display: flex;
  gap: 0.625rem;
  margin-bottom: var(--space-4);
  flex-wrap: nowrap;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.seg-row::-webkit-scrollbar { display: none; }
.seg-row > .seg { flex-shrink: 0; }

@media (max-width: 480px) {
  .seg > :where(button, a) {
    font-size: 0.625rem;
    padding: 0.4375rem 0.5rem;
    letter-spacing: 0.04em;
  }
  .seg-row { gap: 0.5rem; }
}

/* ─── "See all →" link ─────────────────────────────────────────────
   Quiet trailing link under a list (home feed's "More →", issues
   list footer). Dotted underline that firms up on hover. */
.link-more {
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--ink-soft);
  /* Kill the base :where(a) underline — the dotted border-bottom below
     is this link's only underline. Without this both stack (solid +
     dotted double underline). */
  text-decoration: none;
  border-bottom: 1px dotted var(--ink-faint);
  padding-bottom: 1px;
  transition: color var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out);
}
.link-more:hover {
  color: var(--ink);
  border-bottom-color: var(--ink);
}

/* ─── Page shells without a local width ────────────────────────────
   These pages size their column here rather than in their own css:
   issues (list/new/saved/trash), post reader (also worn by
   /issues/:id via .post-shell), search, and the settings layout.
   Install, pricing, and purchase share the narrower form column —
   focused single-task pages, not multi-section surfaces. */
/* Install lives in the marketing column (820px) alongside feed / home /
   learn so its left edge and top line up with those pages — it reads as
   the same surface, not a narrower focused-task page. */
.issues-shell,
.post-shell,
.search-shell,
.settings-shell,
.install-shell {
  max-width: var(--container-marketing);
  margin: 0 auto;
  padding: 0 var(--space-8);
}

/* Purchase and pricing sit in the SAME wide marketing column as
   feed / install / learn, so their left edge and top line up — no lurch
   when navigating between them. But their content is a form / reading
   column, so we cap each block at the form width and LEFT-align it
   within the wide shell (not centered in the middle of the column). */
.purchase-shell,
.pricing-shell,
.business-shell {
  max-width: var(--container-marketing);
  margin: 0 auto;
  padding: 0 var(--space-8);
}
.purchase-shell > *,
.pricing-shell > *,
.business-shell > * {
  max-width: var(--container-form);
}

@media (max-width: 700px) {
  .issues-shell,
  .post-shell,
  .search-shell,
  .settings-shell,
  .install-shell,
  .purchase-shell,
  .pricing-shell,
  .business-shell { padding: 0 var(--space-5); }
}

@media (max-width: 640px) {
  .issues-shell,
  .post-shell,
  .search-shell,
  .settings-shell,
  .install-shell,
  .purchase-shell,
  .pricing-shell,
  .business-shell { padding: 0 var(--space-4); }
}

/* Content readers claw back gutter on phones — body width is the
   scarce resource on a text page. */
@media (max-width: 480px) {
  .post-shell,
  .search-shell { padding: 0 var(--space-3); }
}

/* ─── Settings / account page title ────────────────────────────────
   The h1 rendered by the settings-page and composer-form layouts
   (`class="account-h1 settings-title"`). Canonical top-level scale:
   48px desktop, 40px on phones. */
.account-h1 {
  font-family: var(--font-sans);
  font-weight: var(--weight-bold);
  font-size: var(--page-title);
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--ink);
  margin: 2rem 0 var(--space-4);
}

@media (max-width: 640px) {
  .account-h1 {
    font-size: 2.5rem;
    margin-top: 1.5rem;
  }
}

/* ─── Button arrow affordance ──────────────────────────────────────
   `<span class="arrow">→</span>` inside a button stays muted within
   the button's color family and brightens on hover. */
button .arrow, .button .arrow {
  color: currentColor;
  opacity: 0.5;
  transition: opacity var(--duration-fast) var(--ease-out);
}
button:hover .arrow, .button:hover .arrow { opacity: 0.7; }
button.is-primary .arrow, .button.is-primary .arrow {
  color: rgba(255, 255, 255, 0.5);
}

/* ─── Toggle switch ────────────────────────────────────────────────
   The auto-renew switch on /purchase and /account (billing). A
   <button class="toggle"> flipping .is-on; the knob is the ::after.
   Absorbed from the old package — the successor there is the ui
   switch template, which the server hasn't adopted yet. */
.toggle {
  width: 2.375rem;
  height: 1.375rem;
  background: var(--ink-faint);
  border-radius: var(--radius-full);
  position: relative;
  cursor: pointer;
  flex-shrink: 0;
  border: none;
  padding: 0;
  transition:
    background-color 200ms var(--ease-out),
    box-shadow 150ms var(--ease-out);
}

.toggle::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 1.125rem;
  height: 1.125rem;
  background: #ffffff;
  border-radius: 50%;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
  transition:
    transform 200ms cubic-bezier(0.4, 0, 0.2, 1),
    width 80ms var(--ease-out);
}

.toggle.is-on { background: var(--accent); }
.toggle.is-on::after { transform: translateX(1rem); }

.toggle:hover:not(:disabled) { background: var(--ink-dim); }
.toggle.is-on:hover:not(:disabled) { background: var(--accent-deep); }

/* Pressed: the knob stretches toward the direction it will travel. */
.toggle:active:not(:disabled)::after { width: 1.375rem; }
.toggle.is-on:active:not(:disabled)::after {
  transform: translateX(0.75rem);
  width: 1.375rem;
}

.toggle:focus-visible {
  outline: none;
  box-shadow:
    0 0 0 2px var(--bg),
    0 0 0 4px var(--accent-deep);
}

.toggle:disabled {
  background: var(--rule);
  cursor: not-allowed;
  opacity: 0.6;
}

.toggle:disabled::after {
  background: var(--bg-soft);
  box-shadow: none;
}

/* ─── Terminal copy chip ───────────────────────────────────────────
   Comfier than the package default (4px vertical, fixed 6.5rem):
   real padding on both axes, width from content with the same
   minimum so the chip doesn't jump when "copy" flips to "✓ copied". */
.terminal > .copy {
  padding: var(--space-2) var(--space-3);
  width: auto;
  min-width: 6.5rem;
}

/* ─── Links ────────────────────────────────────────────────────────
   A bare <a> is pinned to the brand blue rather than derived from the
   text around it.

   @elements/style computes a link as
   `oklch(from currentColor calc(l + (l - 0.5) * 0.2) var(--link-c) var(--link-h))`,
   which keeps the surrounding text's lightness and swaps in the theme's
   chroma and hue. On a dark ground the surrounding ink is near-white, so
   the result asks for lightness 0.93 at chroma 0.12, which no blue in
   sRGB can be. Every browser then gamut maps it, and they disagree:
   Chrome lands on #94F6FF, a pale cyan, and Safari on iOS lands on a
   yellow-green. A link colour that changes hue by browser is not a
   colour, so the site states it.

   One value per mode, the same blue the founder letter already uses.
   Scoped to `a:not([class])`, not to `a`: this file is unlayered, and an
   unlayered rule beats every layered one whatever its specificity, so a
   bare `a` here would repaint the brand lockup and the buttons too.
   Matching only links with no class of their own leaves anything that
   already states a colour exactly where it was. */
a:not([class]) {
  color: #2076B5;
  text-decoration-color: rgba(32, 118, 181, 0.4);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) a:not([class]) {
    color: #7FC4F0;
    text-decoration-color: rgba(127, 196, 240, 0.4);
  }
}

:root[data-theme="dark"] a:not([class]) {
  color: #7FC4F0;
  text-decoration-color: rgba(127, 196, 240, 0.4);
}

/* iOS Safari zooms the page when a field under 16px takes focus. Touch
   screens get 16px fields so pinch zoom can stay enabled (see the
   viewport tag in shared-head). */
@media (hover: none) and (pointer: coarse) {
  input:not([type="checkbox"]):not([type="radio"]),
  textarea,
  select {
    font-size: max(16px, 1em);
  }
}

/* Copy feedback on the surface that was clicked. The button flipping to
   "copied" sits in a corner the eye is not on, and a ring alone was lost
   under the hover shadow, so nobody saw either. The surface itself takes an
   accent wash that fades back out.

   Driven by the same `copied` flag the copy button reads, which
   clipboard.ts clears after 1.8s, so there is no timer here; the class
   going on at the click is what starts the animation. The wash is an
   overlay above the surface's children, because inner boxes (the agent
   composer's field) have grounds of their own that would hide anything
   painted on the outer one. */
.is-copyable { position: relative; cursor: pointer; }

.is-copyable.is-copied {
  /* !important: several surfaces set a hover shadow at higher specificity,
     and the pointer is always over the thing just clicked. */
  box-shadow: 0 0 0 2px var(--accent) !important;
}

.is-copyable.is-copied::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  background: var(--accent);
  pointer-events: none;
  animation: copyable-wash 1s ease-out forwards;
}

@keyframes copyable-wash {
  0%   { opacity: 0.5; }
  35%  { opacity: 0.3; }
  100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .is-copyable.is-copied::before { animation: none; opacity: 0.15; }
}
