/* ===================================================================================
   Pinned — shared styles
   Cartoon look: a sky above, a ground strip below, chunky ink outlines and offset
   "sticker" shadows on every surface, matching the pin mascots.

   Themes (app/themes.py) only change the variables in :root: each theme's file in
   static/themes/ is loaded after this one. The defaults below are the Jungle theme,
   so the site still looks right if a theme file fails to load.
   Artwork: scripts/gen_image.py -> design/source/ -> scripts/build_theme_assets.py.
   Contrast (WCAG): every text/background pair in every theme is >= 4.5:1.
   =================================================================================== */

:root {
  /* Ink & paper */
  --ink: #1c1917;
  --paper: #f7fbf1;
  --cream: #eef6df;
  --text: var(--ink);
  --muted: #4b5e44;          /* 6.2:1 on paper */

  /* Theme palette (Jungle defaults; themes override these) */
  --sky-top: #70bfea;        /* top of the sky scene */
  --sky: #b8e8d7;            /* bottom of the sky scene */
  --sky-pale: #dff5e8;
  --sky-stop-1: 400px;       /* where the page gradient reaches --sky / --sky-pale */
  --sky-stop-2: 700px;
  --grass: #7fb069;          /* avatar, trend bars */
  --floor: #447535;          /* bottom edge of the ground scene (overscroll colour) */
  --leaf: #2e7d32;           /* primary buttons; white text 5.1:1 */
  --leaf-dark: #1f6424;
  --forest: #1d5a2a;         /* links; 6.4:1 on paper */
  --sun: #f5c84c;            /* focus ring, Pro / Max badges */
  --sun-pale: #fdf0c4;       /* hover / highlight surfaces */
  --placeholder: #76866e;
  --rule: #cfe3c2;           /* dashed separators */
  --tint: #e3f1d4;           /* free-tier badge */
  --inactive-bg: #edf2e6;    /* deactivated link rows */

  /* Theme scenery */
  --scene-sky: url("/static/img/themes/jungle/scene-sky.webp");
  --scene-sky-aspect: 2560 / 597;
  --scene-ground: url("/static/img/themes/jungle/scene-ground.webp");
  --scene-ground-aspect: 2560 / 817;
  --scene-ground-height: auto;
  --scene-ground-min: 130px;
  --scene-ground-max: 320px;
  --scene-ground-size: cover;
  --scene-ground-position: center top;
  --scene-ground-repeat: no-repeat;
  --bark: #8a5a2b;           /* wooden sign; cream text 5.5:1 */
  --bark-dark: #6b4420;

  /* Brand accent (the pins) */
  --pin-red: #d63327;
  --pin-red-dark: #b8261b;
  --note-yellow: #ffd84d;

  --danger: #b3261e;
  --success: #1f6b2a;

  /* Shape */
  --outline: 2px solid var(--ink);
  --radius: 16px;
  --radius-sm: 10px;
  --shadow: 4px 4px 0 var(--ink);
  --shadow-sm: 2px 2px 0 var(--ink);

  /* Type */
  --font-display: "Fredoka", "Baloo 2", ui-rounded, "Arial Rounded MT Bold", system-ui, sans-serif;
  --font-body: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --cover-dot: #b8d494;      /* the bento cover's dot pattern, on the grass band */
}
/* The bento page's body text is Nunito (profile.html loads it, bento only). A creator's font
   choice and a custom palette set font-family directly, so they still win. */
body.public:has(> main.profile-bento) { --font-body: "Nunito", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; }

* { box-sizing: border-box; }

/* --- Page: sky above, ground below ------------------------------------------------- */

/* Overscroll below the ground strip matches it. overflow-x: clip keeps the decorative
   layers (the sky art is wider than a phone) from ever making the page scroll sideways. */
html { background: var(--floor); overflow-x: clip; max-width: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  position: relative;
  isolation: isolate;       /* keeps the sky layer (z-index -1) above this background */
  overflow-x: clip;         /* the sky layer is wider than a phone screen */
  font-family: var(--font-body);
  line-height: 1.5;
  color: var(--text);
  background: linear-gradient(180deg, var(--sky-top) 0, var(--sky) var(--sky-stop-1), var(--sky-pale) var(--sky-stop-2), var(--sky-end, var(--cream)) 100%);
}
/* The bento page's own sky (the mockup's): the blue holds longer, to 560 px and 880 px, and the
   page ends on paper, and the ground strip is at least the phone mockup's 150 px (390 x 150; from
   470 px the art's own proportions are taller). Set on the body, so the other pages keep their tuning; a custom palette
   replaces the whole background anyway (body.public.custom-appearance). */
body.public:has(> main.profile-bento) { --sky-stop-1: 560px; --sky-stop-2: 880px; --sky-end: var(--paper); --scene-ground-min: 150px; }
body > main { flex: 1 0 auto; width: 100%; min-width: 0; }
img, svg { max-width: 100%; }

/* Sky banner. Its size is bounded, 1000-1680px wide, so clouds stay a
   sensible size: phones see a centred crop, and big screens don't blow the art up to
   the full window width. Its bottom fades into the gradient above; on screens wider
   than the banner its sides fade too, so there's never a hard edge. */
body::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0;
  left: 50%;
  translate: -50% 0;
  width: clamp(1000px, 100%, 1680px);
  aspect-ratio: var(--scene-sky-aspect);
  background: var(--scene-sky) top center / 100% auto no-repeat;
  -webkit-mask-image: linear-gradient(180deg, #000 70%, transparent);
  mask-image: linear-gradient(180deg, #000 70%, transparent);
  pointer-events: none;
}
@media (min-width: 1681px) {
  body::before {
    -webkit-mask-image:
      linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent),
      linear-gradient(180deg, #000 70%, transparent);
    -webkit-mask-composite: source-in;
    mask-image:
      linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent),
      linear-gradient(180deg, #000 70%, transparent);
    mask-composite: intersect;
  }
}

/* On the Jungle bento page the sky box is the mockup's own: 611 px tall (424 px on a phone) with the art,
   336 px (233 px) high, wholly inside the opaque 70 % of the mask, so none of it fades (the cloud undersides
   and the sun-ray tips stay). Another theme keeps the art-sized box and its fade: its art ends in its own
   colour, not the mockup's gradient, and would show a seam. */
body.public[data-theme="jungle"]:has(> main.profile-bento)::before { aspect-ratio: auto; height: 611px; max-height: 100%; }
@media (max-width: 699px) {
  body.public[data-theme="jungle"]:has(> main.profile-bento)::before { height: 424px; }
}

/* Ground strip. Anchored at the top so hilltops, trees and rocks are never cropped;
   on wide screens only plain ground at the bottom is trimmed, meeting --floor below. */
.scenery {
  flex: none;
  width: 100%;
  aspect-ratio: var(--scene-ground-aspect);
  height: var(--scene-ground-height);
  min-height: var(--scene-ground-min);
  max-height: var(--scene-ground-max);
  margin-top: 2rem;
  background-image: var(--scene-ground);
  background-size: var(--scene-ground-size);
  background-position: var(--scene-ground-position);
  background-repeat: var(--scene-ground-repeat);
  pointer-events: none;
}
/* The bento page's footer is followed closely by the ground (the mockup: about 27 px below the pill). */
body.public:has(> main.profile-bento) .scenery { margin-top: 8px; }

h1, h2, h3, .brand, button, a.button, .tier-badge, .auth-headline {
  font-family: var(--font-display);
}
h1, h2, h3 { font-weight: 600; letter-spacing: 0.005em; line-height: 1.15; }
h1 { font-size: clamp(1.7rem, 4vw, 2.2rem); }
/* Headings that sit directly on the illustrated sky get a cream halo, so cloud
   outlines behind them never cut through the letters. */
.container > h1, .profile-header h1, .auth-headline {
  text-shadow:
    2px 2px 0 var(--paper), -2px -2px 0 var(--paper), 2px -2px 0 var(--paper), -2px 2px 0 var(--paper),
    0 2px 0 var(--paper), 0 -2px 0 var(--paper), 2px 0 0 var(--paper), -2px 0 0 var(--paper);
}

/* Text that sits straight on the themed background (not inside a card) gets a translucent
   paper backing, so the scenery art never cuts through it (feature 012). 88% paper keeps
   the text colours above 4.5:1 even over the darkest art (tests/unit/test_backing_contrast.py). */
.text-backing, .back-link, [data-app-root] > p, [data-app-root] > h1,
.container > h1, .auth-headline, .verify .auth-subline, .brand-lockup-word {
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  border-radius: var(--radius-sm);
  padding: 0.3rem 0.8rem;
  width: fit-content;
  max-width: 100%;
  text-shadow: none;
}
.auth-hero .auth-headline { margin-inline: auto; }
.text-backing { margin-top: 0.75rem; }
p.back-link { margin: 0 0 0.75rem; }

a { color: var(--forest); text-underline-offset: 0.15em; }
a:hover { color: var(--leaf-dark); }
:focus-visible { outline: 3px solid var(--sun); outline-offset: 2px; }

/* --- Header ----------------------------------------------------------------------- */

.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem 1rem;
  max-width: 1100px;
  width: 100%;
  margin: 0 auto;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-weight: 700;
  font-size: 1.45rem;
  text-decoration: none;
  color: var(--ink);
}
.brand img { width: 44px; height: 44px; filter: drop-shadow(0 2px 2px rgba(28, 25, 23, 0.2)); }
.site-header nav { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; }
/* Every header item (the links and the Log out button) shares this one style and size. */
.nav-item {
  display: inline-flex;
  align-items: center;
  box-sizing: border-box;
  min-height: 2.3rem;
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.98rem;
  line-height: 1.2;
  color: var(--ink);
  text-decoration: none;
  background: var(--paper);
  border: var(--outline);
  border-radius: 999px;
  padding: 0.3rem 0.9rem;
  box-shadow: var(--shadow-sm);
  cursor: pointer;
}
.nav-item:hover { background: var(--sun-pale); color: var(--ink); }
/* The signed-out "Sign up" pill (feature 024, FR-005) and the current page's pill. */
.nav-item[aria-current="page"] { background: var(--tint); }
.nav-item.nav-cta { background: var(--leaf); color: #fff; font-weight: 600; }
.nav-item.nav-cta:hover { background: var(--leaf-dark); color: #fff; }
.nav-lock { width: 1rem; height: 1rem; margin-left: 0.35rem; vertical-align: -0.125em; }

/* The menu: a CSS-only <details> (feature 012). Below 700 px its summary is a button at the
   top right that opens a panel; from 700 px the links show inline and the button is gone. */
.nav-toggle {
  list-style: none;
  display: none;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  color: var(--ink);
  background: var(--paper);
  border: var(--outline);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
}
.nav-toggle::-webkit-details-marker { display: none; }
.nav-toggle:hover, .nav-menu[open] > .nav-toggle { background: var(--sun-pale); }
@media (max-width: 699.98px) {
  .site-header .site-nav:not(.has-menu) { display: none; }
  .nav-toggle { display: inline-flex; }
  .nav-menu { position: relative; }
  .site-header .nav-menu > nav {
    position: absolute;
    z-index: 20;
    top: calc(100% + 0.5rem);
    right: 0;
    flex-direction: column;
    align-items: stretch;
    flex-wrap: nowrap;
    min-width: 12.5rem;
    max-width: calc(100vw - 2rem);
    padding: 0.6rem;
    gap: 0.45rem;
    background: var(--paper);
    border: var(--outline);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
  }
  .site-header .nav-menu > nav .nav-item { width: 100%; min-height: 2.75rem; box-shadow: none; }
  .site-header .nav-menu > nav form.inline { display: block; }
}
@media (min-width: 700px) {
  /* Wide screens show the inline .site-nav; the menu (button and panel) is not rendered. */
  .nav-menu { display: none; }
}

/* The signed-in user menu (feature 027): two pills and one details.user-menu. The switch is in em so larger
   text moves it with the pills. Rows keep .nav-item (useCurrentNavItem marks them) and are styled here. */
.site-header .nav-pills { display: contents; }
.site-header .nav-pills .nav-item { display: inline-flex; }
@media (max-width: 43.74em) { .site-header .nav-pills { display: none; } }
@media (min-width: 43.75em) { .site-header .menu-nav { display: none; } }
.user-menu { position: relative; }
.user-menu > summary {
  list-style: none; display: inline-flex; align-items: center; gap: 0.3rem; box-sizing: border-box;
  min-height: 2.75rem; padding: 0.2rem 0.35rem 0.2rem 0.65rem; cursor: pointer; color: var(--ink);
  background: var(--paper); border: var(--outline); border-radius: 999px; box-shadow: var(--shadow-sm);
}
.user-menu > summary::-webkit-details-marker { display: none; }
.user-menu > summary:hover, .user-menu[open] > summary { background: var(--sun-pale); }
.user-menu:not([open]):has(.menu-account [aria-current="page"], .menu-owner [aria-current="page"]) > summary:not(:hover) { background: var(--tint); }
.user-menu .menu-avatar { width: 2.125rem; height: 2.125rem; margin: 0; flex: none; font-size: 1rem; border-width: 2px; box-shadow: none; }
.menu-panel {
  position: absolute; z-index: 20; top: calc(100% + 0.5rem); right: 0; box-sizing: border-box;
  width: 17rem; max-width: calc(100vw - 2rem); max-height: calc(100dvh - 5rem); overflow-y: auto;
  padding: 0.5rem; background: var(--paper); border: var(--outline); border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.menu-identity { display: flex; align-items: center; gap: 0.6rem; padding: 0.3rem 0.5rem 0.5rem; min-width: 0; }
.menu-id-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }
.menu-id-text > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.menu-id-text strong { font-family: var(--font-display); font-weight: 600; }
.menu-id-text span { font-size: 0.9rem; color: var(--muted, var(--ink)); }
.menu-group { display: flex; flex-direction: column; gap: 0.1rem; padding-top: 0.4rem; margin-top: 0.4rem; border-top: 2px dashed #cfe3c2; }
.menu-group:empty { display: none; }
.menu-panel form.inline { display: block; }
.site-header .user-menu .menu-row {
  display: flex; width: 100%; box-sizing: border-box; min-height: 2.75rem; gap: 0.6rem; padding: 0 0.75rem;
  background: transparent; border: 2px solid transparent; border-radius: var(--radius-sm); box-shadow: none;
  font-size: 0.98rem; text-align: left;
}
.site-header .user-menu .menu-row:hover { background: var(--sun-pale); }
.site-header .user-menu .menu-row[aria-current="page"] { background: var(--tint); border-color: var(--ink); }
.menu-ico { width: 1.25rem; height: 1.25rem; flex: none; }
.menu-row .nav-lock { margin-left: auto; }
.menu-theme { padding: 0.25rem 0.9rem 0.4rem; }
.menu-theme label { display: flex; align-items: center; gap: 0.6rem; min-height: 2rem; margin: 0; font-family: var(--font-display); font-weight: 600; font-size: 0.98rem; color: var(--ink); }
.menu-theme-row { display: flex; gap: 0.5rem; margin: 0 -0.4rem; }
.menu-theme select { flex: 1 1 auto; min-width: 0; min-height: 2.75rem; padding: 0 0.25rem 0 0.75rem; font: inherit; text-overflow: ellipsis; border: var(--outline); border-radius: var(--radius-sm); background: #fff; color: var(--ink); }
.menu-theme button { flex: none; min-height: 2.75rem; padding: 0 0.75rem; font-family: var(--font-display); font-weight: 600; color: var(--ink); background: var(--paper); border: var(--outline); border-radius: 999px; box-shadow: var(--shadow-sm); cursor: pointer; }
.menu-theme button:hover { background: var(--sun-pale); }
@media (max-width: 43.74em) { .menu-panel { width: calc(100vw - 2rem); } }
@media (prefers-reduced-motion: no-preference) { .user-menu > summary, .site-header .user-menu .menu-row { transition: background-color 0.12s; } }

/* --- Layout & cards ---------------------------------------------------------------- */

.container { max-width: 780px; margin: 1rem auto; padding: 0 1rem; }
.container > h1 { margin: 0.5rem 0 1rem; }

.card {
  background: var(--paper);
  border: var(--outline);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.25rem 1.35rem;
  margin-bottom: 1.5rem;
}
.card.narrow { max-width: 440px; margin: 2rem auto; }
.card h2 { margin-top: 0; font-size: 1.35rem; }

/* --- Forms ------------------------------------------------------------------------- */

label { display: block; font-weight: 600; margin: 0.8rem 0 0.3rem; }
input, textarea {
  width: 100%;
  padding: 0.6rem 0.75rem;
  border: var(--outline);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--ink);
  font: inherit;
}
input::placeholder, textarea::placeholder { color: var(--placeholder); }
input:focus-visible, textarea:focus-visible { outline: 3px solid var(--sun); outline-offset: 1px; }
input[aria-invalid="true"], textarea[aria-invalid="true"] { border-color: var(--danger); background: #fff5f4; }

button, a.button {
  font-weight: 600;
  font-size: 0.98rem;
  padding: 0.5rem 0.95rem;
  border: var(--outline);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: var(--ink);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: transform 80ms ease, box-shadow 80ms ease, background 120ms ease;
}
button:hover, a.button:hover { background: var(--sun-pale); }
button:active, a.button:active { transform: translate(2px, 2px); box-shadow: none; }
button.primary { background: var(--leaf); color: #fff; }
button.primary:hover { background: var(--leaf-dark); }
button.danger { color: var(--danger); }
button.danger:hover { background: #ffe9e6; }
.card.narrow button.primary,
.auth-card button.primary { width: 100%; margin-top: 1.1rem; padding: 0.7rem 1rem; font-size: 1.1rem; box-shadow: 3px 3px 0 var(--ink); }
form.inline { display: inline; margin: 0; }

.error { color: var(--danger); margin: 0.4rem 0; font-size: 0.95rem; font-weight: 600; }
.success { color: var(--success); font-weight: 600; }
.notice {
  background: var(--sun-pale); border: var(--outline); border-radius: var(--radius-sm);
  padding: 0.5rem 0.75rem; margin: 0.4rem 0; font-weight: 600;
}
.hint, .muted { color: var(--muted); font-size: 0.92rem; }
.center { text-align: center; }
.row { display: flex; align-items: center; gap: 0.75rem; margin-top: 0.75rem; }

.prefixed { display: flex; align-items: stretch; }
.prefix {
  padding: 0.6rem 0.7rem;
  border: var(--outline);
  border-right: none;
  border-radius: var(--radius-sm) 0 0 var(--radius-sm);
  background: var(--sun-pale);
  color: var(--ink);
  font-weight: 700;
}
.prefixed input { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }

.or-divider { display: flex; align-items: center; gap: 0.75rem; margin: 1rem 0; color: var(--muted); }
.or-divider::before, .or-divider::after { content: ""; flex: 1; border-top: 2px dashed var(--rule); }
a.button { display: block; text-align: center; text-decoration: none; }

/* --- Dashboard --------------------------------------------------------------------- */

.plan { display: flex; align-items: center; flex-wrap: wrap; gap: 0.75rem; }
.tier-badge {
  font-size: 0.85rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  padding: 0.15rem 0.7rem; border-radius: 999px; border: var(--outline); background: var(--tint);
}
.tier-badge.pro { background: var(--sun-pale); color: var(--ink); }
.tier-badge.max { background: var(--sun); color: var(--ink); }
a.button.inline-button { display: inline-block; padding: 0.3rem 0.8rem; font-size: 0.95rem; }
.plan-billing { margin-top: 0.75rem; border-top: 2px dashed var(--rule); padding-top: 0.6rem; }
.plan-billing p { margin: 0 0 0.5rem; }
.plan-billing .error { display: block; }
.plan-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.interval-panel { margin-top: 0.6rem; }

/* --- Plans (feature 003) ------------------------------------------------------------- */

.plan-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1rem; }
.plan-option { display: flex; flex-direction: column; }
.plan-option.current { box-shadow: 4px 4px 0 var(--leaf); }
.plan-option ul { padding-left: 1.2rem; margin: 0.5rem 0 1rem; }
.plan-price { font-family: var(--font-display); font-weight: 600; font-size: 1.15rem; margin: 0.25rem 0; }
.plan-saving { display: inline-block; font-size: 0.85rem; color: var(--forest); }
.plan-current { font-weight: 700; color: var(--success); margin-top: auto; }
.plan-buttons { display: grid; gap: 0.5rem; margin-top: auto; }
.plan-buttons form { margin: 0; }
.plan-buttons button { width: 100%; }
.fine-print { font-size: 0.85rem; color: var(--muted); }

/* The signed-in Plans page: large cards in the look of the public pricing page. Scoped to .plans-page so the
   dashboard's .plan-card and the other pages are untouched. */
main.container:has(.plans-page) { max-width: 1068px; }
.plans-page { --chk: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='10.6' fill='%232e7d32' stroke='%231c1917' stroke-width='1.8'/%3E%3Cpath d='M7.4 12.3l3.1 3.1 6.1-6.3' fill='none' stroke='%23fff' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
.plans-page .plan-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: 24px; row-gap: 0; margin-top: 8px; }
.plans-page .plan-grid.plan-grid-two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.plans-page .plan-option { position: relative; grid-row: span 4; display: grid; grid-template-rows: subgrid; row-gap: 0; margin-top: 26px; padding: 28px; min-width: 0; }
.plans-page .plan-option.is-pro { box-shadow: 6px 6px 0 var(--leaf); }
.plans-page .plan-option.current { background: color-mix(in srgb, var(--tint) 40%, var(--paper)); }
.plans-page .plan-top { display: flex; align-items: center; gap: 14px; }
.plans-page .plan-top h2 { margin: 0; font-size: 30px; line-height: 1.1; }
.plans-page .plan-top .tier-badge { margin-left: auto; }
.plans-page .plan-icon { display: flex; flex: none; align-items: center; justify-content: center; width: 48px; height: 48px; border: var(--outline); border-radius: 12px; background: var(--tint); box-shadow: var(--shadow-sm); color: var(--leaf); }
.plans-page .plan-icon.pro { background: var(--sun-pale); }
.plans-page .plan-icon.max { background: var(--sun); }
.plans-page .plan-flag { position: absolute; top: -18px; left: 50%; translate: -50% 0; display: inline-flex; align-items: center; gap: 6px; width: max-content; padding: 5px 14px; background: var(--leaf); border: var(--outline); border-radius: 999px; box-shadow: var(--shadow-sm); color: #fff; font: 600 15px/20px var(--font-display); white-space: nowrap; }
.plans-page .plan-flag svg { flex: none; }
.plans-page .plan-pricing { margin-top: 22px; }
.plans-page .plan-price { margin: 0; font-size: inherit; line-height: 1.1; }
.plans-page .plan-amount { font: 700 48px/1 var(--font-display); letter-spacing: -0.01em; }
.plans-page .plan-per { color: var(--muted); font-weight: 700; font-size: 18px; }
.plans-page .plan-year { margin: 10px 0 0; color: var(--muted); font-weight: 600; font-size: 15.5px; line-height: 1.5; }
.plans-page .save { display: inline-block; padding: 0 9px; border-radius: 999px; background: var(--tint); color: var(--forest); font-weight: 700; white-space: nowrap; }
.plans-page .plan-action { margin-top: 22px; display: flex; flex-direction: column; gap: 0.5rem; }
.plans-page .plan-action > * { margin: 0; }
.plans-page .plan-action .plan-buttons { margin-top: 0; }
.plans-page .plan-current { margin-top: 0; }
.plans-page .plan-list { margin-top: 24px; padding-top: 20px; border-top: 2px dashed var(--rule); }
.plans-page .plan-list p { margin: 0 0 12px; font-weight: 700; font-size: 15.5px; line-height: 1.45; }
.plans-page .mk-checks { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; line-height: 1.45; font-size: 16px; }
.plans-page .mk-checks li { display: flex; align-items: flex-start; gap: 10px; }
.plans-page .mk-checks li::before { content: ""; flex: none; width: 22px; height: 22px; margin-top: 1px; background: var(--chk) center/contain no-repeat; }
@media (max-width: 899px) {
  .plans-page .plan-grid, .plans-page .plan-grid.plan-grid-two { grid-template-columns: minmax(0, 1fr); max-width: 560px; margin-inline: auto; }
  .plans-page .plan-option { grid-row: auto; display: flex; flex-direction: column; }
}
@media (max-width: 699px) { .plans-page .plan-option { padding: 24px 20px; } }

/* Privacy / terms pages */
.legal h1 { margin-top: 0; }
.legal h2 { margin-top: 1.4rem; font-size: 1.2rem; }
.legal-links { margin-top: 0.4rem; font-weight: 500; }

.upgrade-prompt {
  background: var(--sun-pale);
  border: var(--outline);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  padding: 0.7rem 0.9rem;
  margin: 0.75rem 0;
}
.upgrade-prompt h2 { margin-top: 0; }

.add-link .fields, .link-edit { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.add-link input, .link-edit input { flex: 1 1 200px; width: auto; }

.links { list-style: none; padding: 0; margin: 1rem 0 0; display: grid; gap: 0.75rem; }
.link-row {
  background: #fff;
  border: var(--outline);
  border-radius: var(--radius-sm);
  padding: 0.75rem;
}
.link-row.inactive { background: var(--inactive-bg); }
.link-row.inactive .link-edit input { color: var(--muted); }
.link-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.6rem; }
.link-actions .spacer { flex: 1; }
.link-actions button { padding: 0.3rem 0.7rem; font-size: 0.9rem; }
.status {
  font-family: var(--font-display);
  font-size: 0.8rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em;
  padding: 0.05rem 0.55rem; border-radius: 999px; border: 2px solid var(--leaf); color: var(--leaf);
}
.inactive .status { border-color: var(--muted); color: var(--muted); }
.clicks { font-size: 0.92rem; }

.appearance-form fieldset { border: none; padding: 0; margin: 0.9rem 0; }
.appearance-form legend { font-weight: 700; margin-bottom: 0.4rem; }
.choices { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.choices label {
  display: inline-flex; align-items: center; gap: 0.4rem; margin: 0; font-weight: 500;
  background: #fff; border: var(--outline); border-radius: 999px; padding: 0.2rem 0.7rem 0.2rem 0.45rem;
}
.choices input { width: auto; margin: 0; }
.swatch { width: 1.1rem; height: 1.1rem; border-radius: 50%; border: var(--outline); display: inline-block; }
.appearance-preview { border-radius: var(--radius); border: var(--outline); padding: 1rem; margin-top: 1rem; }
.appearance-preview .public-link { display: block; max-width: 280px; margin: 0.5rem auto 0; }

.trend { width: 100%; }
.trend-panel { margin-top: 0.6rem; }
.trend-panel table { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
.trend-panel th, .trend-panel td { text-align: left; padding: 0.25rem 0.4rem; border-bottom: 2px dashed var(--rule); }
.trend-bar {
  display: inline-block; height: 0.75rem; min-width: 4px;
  background: var(--grass); border: 2px solid var(--ink); border-radius: 999px; vertical-align: middle;
}
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* --- Public profile ---------------------------------------------------------------- */

main.profile { max-width: 580px; margin: 0 auto; padding: 3.5rem 1rem 0; }
/* One solid card holds the avatar, name, bio and links, so they stay readable over
   the theme scenery. The ad and footer sit outside it. */
.profile-card {
  background: var(--paper);
  color: var(--ink);
  border: var(--outline);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 2rem 1.25rem 1.5rem;
}
.profile-header { text-align: center; margin-bottom: 1.5rem; }
.avatar {
  width: 96px; height: 96px; margin: 0 auto 0.6rem;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--grass); color: var(--ink);   /* not yellow: that's the sun's job */
  border: 3px solid var(--ink); box-shadow: var(--shadow);
  font-family: var(--font-display); font-size: 2.6rem; font-weight: 700;
  position: relative;
}
/* Feature 005: the profile picture covers the letter. A picture that fails to load has
   alt="" and renders nothing, so the letter shows through (no script needed). */
.avatar-img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  border-radius: 50%;
  object-fit: cover;
  background: transparent;
}
.profile-header h1 { margin: 0.3rem 0; font-size: 1.8rem; }
.bio { white-space: pre-line; margin: 0.5rem auto 0; max-width: 42ch; color: var(--ink); }
.public-links { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.9rem; }
/* Three columns, [logo] [title] [spacer], with equal side columns, so every title is
   centered on its button and titles line up whether or not a button has a logo. */
.public-link {
  display: grid;
  grid-template-columns: 44px 1fr 44px;
  align-items: center;
  column-gap: 0.5rem;
  padding: 0.95rem 0.75rem;
  text-align: center;
  background: var(--cream);
  border: var(--outline);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  color: var(--ink);
  text-decoration: none;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.08rem;
  overflow-wrap: anywhere;
  transition: transform 90ms ease, box-shadow 90ms ease, background 120ms ease;
}
.public-link:hover { background: var(--sun-pale); color: var(--ink); transform: translate(-1px, -2px); box-shadow: 5px 6px 0 var(--ink); }
.public-link:active { transform: translate(3px, 3px); box-shadow: 1px 1px 0 var(--ink); }
.link-logo-slot { width: 40px; height: 32px; display: flex; align-items: center; justify-content: flex-start; }
.link-logo {
  display: block; width: 32px; height: 32px;
  border-radius: calc(var(--radius-sm, 6px) / 2);
  object-fit: cover;
  position: relative;
}
/* A logo that fails to load (blocked, offline): browsers draw pseudo-elements only on a
   broken image, so this covers the broken-image frame with the button's own colour and
   the button shows just its title. No script involved. */
.link-logo-slot, .link-logo { background-color: inherit; }
.link-logo::before {
  content: "";
  position: absolute; inset: -1px;
  background-color: inherit;
  border-radius: inherit;
}
/* Outline buttons are see-through (and tint on hover), so the slot and logo stay transparent;
   only the broken-image cover needs a solid colour: the card's, which the buttons sit on. */
.btn-outline .link-logo-slot, .btn-outline .link-logo { background-color: transparent; }
.btn-outline .link-logo::before { background-color: var(--card-bg, var(--paper)); }
/* Feature 006: a platform's logo (inline SVG from the page's sprite) in the button's text colour. */
svg.link-logo { width: 28px; height: 28px; border-radius: 0; color: inherit; background-color: transparent; }
svg.link-logo.mono { color: var(--btn-mono, #000000); }   /* LinkedIn: black or white only */
.btn-outline svg.link-logo.mono { color: var(--icon-mono, #000000); }
.link-title { min-width: 0; overflow-wrap: anywhere; }
.link-spacer { width: 44px; }
.made-with {
  text-align: center; margin: 2rem auto 0; width: fit-content; max-width: 100%;
  font-size: 0.9rem; font-weight: 600;
  background: var(--paper); border: 2px solid var(--ink); border-radius: var(--radius-sm);
  padding: 0.4rem 0.9rem;
}

/* --- Social icons (feature 006) ------------------------------------------------------ */

/* The page's inline sprite: symbols only, never drawn itself. */
.icon-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
/* One centered row that wraps, inside the card; every target at least 44 x 44 px. */
.social-icons {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 0.15rem 0.3rem;
  margin: 0.6rem auto 0; max-width: 100%;
}
.social-icon {
  display: inline-grid; place-items: center;
  width: 44px; height: 44px;
  border-radius: 50%;
  color: var(--icon, var(--ink));
  transition: transform 90ms ease;
}
.social-icon:hover { color: var(--icon, var(--ink)); transform: translateY(-2px); }
.social-icon svg { display: block; width: 26px; height: 26px; }
.social-icon.mono, .social-icon.mono:hover { color: var(--icon-mono, #000000); }   /* LinkedIn */

/* --- Page appearance (feature 006, every plan) --------------------------------------------
   A custom palette overrides the theme with CSS variables from a validated, server-side set
   (app.appearance): flat background, card, buttons, derived text and icon colours. */
body.public.custom-appearance { background: var(--page-bg); color: var(--page-text); font-family: var(--page-font); }
/* A flat custom page: no theme sky art (FR-005), so its image is never requested either. */
body.public.custom-appearance::before { content: none; background: none; }
.custom-appearance h1, .custom-appearance .public-link, .custom-appearance .avatar, .custom-appearance .made-with-cta { font-family: var(--page-font); }
.custom-appearance .profile-card { background: var(--card-bg); color: var(--card-text); }
.custom-appearance .profile-header h1 { text-shadow: none; }
.custom-appearance .bio, .custom-appearance .profile-card .muted { color: inherit; }
.custom-appearance .public-link,
.custom-appearance .public-link:hover {
  background: var(--btn-bg); color: var(--btn-text);
  border-color: var(--btn-outline, var(--ink));   /* an outline when the button nearly matches the card */
}
/* Card and background the same colour (e.g. a page carried over from before 006): no frame. */
.custom-appearance.card-flat .profile-card { border: none; box-shadow: none; }
/* The footer sits on the page background, with the page's text colour. */
.custom-appearance .made-with, .custom-appearance .made-with-row, .custom-appearance .made-with-brand,
.custom-appearance .made-with .report-footer, .custom-appearance .made-with .legal-links {
  background: none; border: none; box-shadow: none; color: inherit;
}
.custom-appearance .made-with a { color: inherit; }
.custom-appearance .made-with-divider { background: currentColor; opacity: 0.35; }
/* Fonts on Theme default (body classes; the stacks match app.models.FONTS). */
.font-serif { --page-font: Georgia, Cambria, Times New Roman, serif; }
.font-mono { --page-font: ui-monospace, Menlo, Consolas, monospace; }
.font-humanist { --page-font: Trebuchet MS, Segoe UI, Candara, sans-serif; }
body.font-serif, body.font-mono, body.font-humanist,
:is(.font-serif, .font-mono, .font-humanist) :is(h1, .public-link, .avatar, .made-with-cta) { font-family: var(--page-font); }
.btn-pill .public-link { border-radius: 999px; }
.btn-square .public-link { border-radius: 0; }
.btn-outline .public-link,
.custom-appearance.btn-outline .public-link { background: transparent; border: 2px solid currentColor; color: inherit; box-shadow: none; }
.btn-outline .public-link:hover,
.custom-appearance.btn-outline .public-link:hover { background: rgba(127, 127, 127, 0.12); color: inherit; }

/* Not found / error pages */
.lost { text-align: center; }
.not-found { margin-top: 1rem; }

/* --- Auth pages (log in, sign up, complete signup) --------------------------------- */

.auth-page .site-header { max-width: 1100px; }

.auth {
  max-width: 1000px;
  margin: 0 auto;
  padding: 1rem 1rem 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 430px);
  gap: 3rem;
  align-items: center;
}
.auth-hero { text-align: center; }
/* Brand lockup (auth pages): the round icon over the wordmark. The icon sits straight on the
   scenery (no backing); only the wordmark text gets the shared text backing above. */
.brand-lockup {
  display: flex; flex-direction: column; align-items: center; gap: 0.25rem;
  width: fit-content; max-width: 100%; margin: 0 auto 0.5rem;
  padding: 1rem 2rem 0.75rem;
}
.brand-lockup img { width: 112px; height: 112px; filter: drop-shadow(0 6px 8px rgba(28, 25, 23, 0.22)); }
.brand-lockup-word {
  font-family: var(--font-display);
  font-weight: 700; font-size: clamp(2.4rem, 6vw, 3.4rem); line-height: 1; color: var(--ink);
}
/* Pin mascots (app/static/img/pins/): transparent die-cut stickers straight on the scenery,
   never on a backing box. They sit directly above a page headline. */
.pin-mascot,
.brand-lockup-mascot img {
  display: block; height: auto; width: min(160px, 50vw); max-width: 100%; margin: 0 auto;
  filter: drop-shadow(0 8px 10px rgba(28, 25, 23, 0.2));
  animation: pin-bob 4.5s ease-in-out infinite;
}
.lost .pin-mascot, .construction-hero .pin-mascot { width: min(180px, 50vw); }
@keyframes pin-bob {
  0%, 100% { translate: 0 0; }
  50% { translate: 0 -8px; }
}
.auth-headline {
  margin: 0.5rem 0 0.25rem;
  font-size: clamp(2.1rem, 5vw, 3.1rem);
  font-weight: 700;
  line-height: 1.05;
  color: var(--ink);
}
.auth-subline {
  display: inline-block; margin: 0; font-size: 1.1rem; font-weight: 600;
  background: var(--paper); border: var(--outline); border-radius: 999px; padding: 0.15rem 0.9rem;
  box-shadow: var(--shadow-sm);
}
.auth-card { margin: 0; padding: 1.75rem; border-radius: 20px; box-shadow: 6px 6px 0 var(--ink); }
.auth-card h1 { margin-top: 0; font-size: 1.8rem; }
.auth-card a { font-weight: 600; }

/* Plan choice and terms on the sign-up forms (feature 012) */
.auth-card select {
  width: 100%; padding: 0.6rem 0.75rem; min-height: 44px;
  border: var(--outline); border-radius: var(--radius-sm);
  background: #fff; color: var(--ink); font: inherit; cursor: pointer;
}
.auth-card select:focus-visible { outline: 3px solid var(--sun); outline-offset: 1px; }
.terms-check { display: flex; align-items: flex-start; gap: 0.6rem; margin: 1rem 0 0.2rem; }
.terms-check input { width: 1.4rem; height: 1.4rem; flex: none; margin: 0.15rem 0 0; accent-color: var(--leaf); }
.terms-check label { margin: 0; font-weight: 500; }
.verify .logout-form { margin-top: 0.75rem; }
.verify .logout-form button { width: 100%; }
a.button.primary { background: var(--leaf); color: #fff; }
a.button.primary:hover { background: var(--leaf-dark); color: #fff; }
a.button.primary-link { background: var(--leaf); color: #fff; margin-top: 1.1rem; padding: 0.7rem 1rem; font-size: 1.05rem; }
a.button.primary-link:hover { background: var(--leaf-dark); color: #fff; }

/* --- Under-construction page (app/construction.py) --------------------------------- */

.construction {
  max-width: 640px;
  margin: 0 auto;
  padding: 1rem 1rem 0;
  text-align: center;
}
.construction-card { margin: 1.5rem auto 0; max-width: 480px; font-size: 1.05rem; }
.construction-card p { margin: 0.4rem 0; }
.construction-page .site-header { justify-content: center; }

/* --- Small screens ------------------------------------------------------------------ */

/* Phones: the header already shows the brand name, so the lockup keeps only the icon. */
@media (max-width: 699.98px) {
  .brand-lockup-word { display: none; }
}

@media (max-width: 800px) {
  .auth { grid-template-columns: minmax(0, 1fr); gap: 1.25rem; padding-top: 0; }
  .brand-lockup { padding: 0.75rem 1.5rem 0.5rem; }
  .brand-lockup img { width: 96px; height: 96px; }
  .pin-mascot, .brand-lockup-mascot img, .lost .pin-mascot, .construction-hero .pin-mascot { width: min(120px, 40vw); height: auto; }
  .auth-headline { font-size: 2rem; }
  .auth-subline { font-size: 1rem; }
  .auth-card { padding: 1.25rem; box-shadow: 4px 4px 0 var(--ink); }
  .brand { font-size: 1.25rem; }
  .brand img { width: 38px; height: 38px; }
}

@media (prefers-reduced-motion: reduce) {
  .pin-mascot, .brand-lockup-mascot img { animation: none; }
  button, a.button, .public-link, .social-icon { transition: none; }
}

/* --- Link menus and reports (feature 013) --------------------------------------------- */

/* The ⋯ button sits over the right-hand spacer of a link button, so titles stay centered.
   The panel uses the card's colours (the custom palette's, or the paper and ink defaults),
   so it is readable with every theme and palette. */
.public-links > li { position: relative; }
.link-menu {
  position: absolute; z-index: 2;
  top: 50%; right: calc(0.75rem + 2px);
  width: 44px; height: 44px; margin-top: -22px;
}
.link-menu[open] { z-index: 20; }
.link-menu summary {
  display: flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 50%;
  list-style: none; cursor: pointer;
  color: var(--btn-text, var(--ink));
}
.link-menu summary::-webkit-details-marker { display: none; }
.link-menu summary:hover, .link-menu[open] summary { background: rgba(127, 127, 127, 0.22); }
.link-menu summary:focus-visible { outline: 3px solid var(--sun); outline-offset: 1px; }
.btn-outline .link-menu summary { color: var(--card-text, var(--ink)); }
.link-menu-panel {
  position: absolute; top: 48px; right: 0;
  display: grid; min-width: 9.5rem; padding: 0.3rem;
  background: var(--card-bg, var(--paper)); color: var(--card-text, var(--ink));
  border: 2px solid var(--card-text, var(--ink)); border-radius: var(--radius-sm);
  box-shadow: 3px 3px 0 var(--card-text, var(--ink));
  text-align: left;
}
.link-menu-panel button, .link-menu-panel a {
  display: block; width: 100%; min-height: 44px; padding: 0.7rem; margin: 0;
  border: none; border-radius: 6px; box-shadow: none; transform: none;
  background: transparent; color: inherit;
  font: inherit; font-size: 0.95rem; font-weight: 600; text-align: left; text-decoration: none; cursor: pointer;
}
.link-menu-panel button[hidden] { display: none; }
.link-menu-panel button:hover, .link-menu-panel a:hover { background: rgba(127, 127, 127, 0.2); color: inherit; }
.link-menu-panel button:focus-visible, .link-menu-panel a:focus-visible { outline: 3px solid var(--sun); outline-offset: -2px; }
.menu-status {
  position: fixed; left: 50%; bottom: 1.25rem; transform: translateX(-50%); z-index: 30;
  margin: 0; padding: 0.45rem 0.9rem; max-width: calc(100vw - 2rem);
  background: var(--ink); color: #fff; border-radius: 999px; font-weight: 600; font-size: 0.95rem;
}
.menu-status:empty { display: none; }
.report-footer { display: block; margin-top: 0.3rem; font-weight: 500; }

.report-form fieldset { border: none; padding: 0; margin: 1rem 0 0; }
.report-form legend { font-weight: 600; padding: 0; margin-bottom: 0.3rem; }
.report-form .reason { display: flex; min-height: 44px; align-items: center; gap: 0.6rem; margin: 0.2rem 0; font-weight: 500; }
.report-form .reason input { width: auto; margin: 0; }
.report-form textarea { min-height: 6rem; resize: vertical; }
.report-form .actions { display: flex; gap: 0.75rem; align-items: center; flex-wrap: wrap; margin-top: 1.1rem; }
.report-form .actions button.primary { width: auto; margin-top: 0; }
/* Off-screen, not display: none, so simple bots still fill it in. */
.hp-field { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }

.admin-links { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.6rem; }
.admin-links a { font-weight: 700; }
.report-list { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; }
.report-item { margin: 0; min-width: 0; }
.report-item h3 { margin: 0 0 0.3rem; font-size: 1.05rem; overflow-wrap: anywhere; }
.check-inline { display: inline-flex; align-items: center; gap: 0.4rem; margin: 0; font-weight: 500; }
.check-inline input { width: 1.2rem; height: 1.2rem; flex: none; margin: 0; accent-color: var(--leaf); }
.report-item dl { margin: 0.4rem 0; display: grid; grid-template-columns: max-content 1fr; gap: 0.15rem 0.75rem; }
.report-item dt { font-weight: 600; }
.report-item dd { margin: 0; overflow-wrap: anywhere; }
.report-item .report-details { white-space: pre-line; }
.report-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.6rem; }
.report-actions form { margin: 0; }

/* --- Profile extras and the Share button (feature 016, both views) ------------------------
   The name line, the two chips and the visitor Share button sit in the profile area of the
   Classic card and of the bento profile tile. */

/* Tile tones and edges. A tile is Card (the palette's card color), Accent (its button color)
   or Soft (80 % card, 20 % button on a custom or flat palette; the theme's light tint on Theme
   default); its text is the readable color for that fill. Theme default uses the theme's own
   colors; a custom or flat palette overrides them with the validated variables the page emits
   (app.appearance). */
:root {
  --tone-card-bg: var(--paper);
  --tone-card-text: var(--ink);
  --tone-accent-bg: var(--grass);
  --tone-accent-text: var(--ink);
  --tone-soft-bg: var(--tint);   /* Theme default: the theme's light green (Canyon: its peach) */
  --tone-soft-text: var(--ink);
  --tile-edge: var(--ink);
  --tile-radius: var(--radius);
}
body.custom-appearance {
  --tone-card-bg: var(--card-bg);
  --tone-card-text: var(--card-text);
  --tone-accent-bg: var(--btn-bg);
  --tone-accent-text: var(--btn-text);
  --tone-soft-bg: var(--soft-bg);
  --tone-soft-text: var(--soft-text);
  --tile-edge: var(--page-text);
  --cover-dot: color-mix(in srgb, var(--tone-accent-text) 28%, transparent);
}
.btn-square { --tile-radius: 0px; }
.btn-pill { --tile-radius: 32px; }

.name-line { margin: 0.25rem 0 0; font-weight: 700; color: var(--muted); overflow-wrap: anywhere; }
.custom-appearance .name-line { color: inherit; }
.chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  display: inline-flex; align-items: center; gap: 5px; max-width: 100%;
  padding: 3px 12px 3px 8px;
  border: 2px solid currentColor; border-radius: 999px;
  font-weight: 700; font-size: 0.88rem; line-height: 1.3;
}
.chip svg { flex: none; }
.chip span { min-width: 0; overflow-wrap: anywhere; }
.chip-location { background: var(--tone-soft-bg); color: var(--tone-soft-text); }
.chip-note { background: var(--tone-accent-bg); color: var(--tone-accent-text); }
.profile-header .chips { justify-content: center; margin: 0.6rem auto 0; }

.share-button {
  display: inline-flex; align-items: center; gap: 6px;
  height: 40px; padding: 0 16px 0 12px;
  border: 2px solid var(--tone-card-text); border-radius: 999px;
  background: var(--tone-card-bg); color: var(--tone-card-text);
  box-shadow: 2px 2px 0 var(--tone-card-text);
  font-size: 15px;
}
.share-button:hover { background: var(--tone-soft-bg); }
.share-button[hidden] { display: none; }
.profile-header .share-button { margin-top: 0.9rem; }
/* A Classic link row's second line (feature 016); the row keeps its three columns. */
.link-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.link-subtitle { font-size: 0.85rem; font-weight: 600; overflow-wrap: anywhere; }

/* --- Bento page (feature 016) -------------------------------------------------------------
   A grid of tiles: 2 columns on phones, 4 from 700 px. Every tile carries span classes from
   app.bento (d-w2 d-h1 m-w2 m-h1); the browser's own auto-placement does the rest, so what you
   see is the reading order. Rows size to their tiles; a tile's min-height is ~160 px (phone)
   or ~200 px (desktop) per row it spans. */

/* 1100 px of grid (four 260 px columns and three 20 px gaps) plus the 16 px side padding. */
main.profile.profile-bento { max-width: 1132px; padding: 1rem 16px 0; }
.bento {
  --tile-gap: 12px; --tile-row: 160px;
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: auto; gap: var(--tile-gap);
}
.m-w1 { grid-column: span 1; }
.m-w2 { grid-column: span 2; }
.m-h1 { grid-row: span 1; --rows: 1; }
.m-h2 { grid-row: span 2; --rows: 2; }
.m-h3 { grid-row: span 3; --rows: 3; }
.m-h4 { grid-row: span 4; --rows: 4; }
@media (min-width: 700px) {
  main.profile.profile-bento { padding-top: 3.5rem; }
  .bento { --tile-gap: 20px; --tile-row: 200px; grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .d-w1 { grid-column: span 1; }
  .d-w2 { grid-column: span 2; }
  .d-w3 { grid-column: span 3; }
  .d-w4 { grid-column: span 4; }
  .d-h1 { grid-row: span 1; --rows: 1; }
  .d-h2 { grid-row: span 2; --rows: 2; }
  .d-h3 { grid-row: span 3; --rows: 3; }
  .d-h4 { grid-row: span 4; --rows: 4; }
}

.tile {
  position: relative; min-width: 0; list-style: none; box-sizing: border-box;
  min-height: calc(var(--rows, 1) * var(--tile-row) + (var(--rows, 1) - 1) * var(--tile-gap));
  border: 2px solid var(--tile-edge); border-radius: var(--tile-radius);
  box-shadow: 4px 4px 0 var(--tile-edge);
  background: var(--tone-card-bg); color: var(--tone-card-text);
  transition: box-shadow 90ms ease;
}
.tile.tone-accent { background: var(--tone-accent-bg); color: var(--tone-accent-text); }
.tile.tone-soft { background: var(--tone-soft-bg); color: var(--tone-soft-text); }
.tile:not(.kind-profile, .kind-heading):hover { box-shadow: 6px 7px 0 var(--tile-edge); }

/* A link, support or social tile: one tap target, icon top left, text bottom left, arrow
   bottom right. The ⋯ menu beside it is a sibling, not inside the link. */
.tile-link {
  display: flex; flex-direction: column; justify-content: flex-end; gap: 10px;
  box-sizing: border-box; height: 100%; padding: 14px;
  border-radius: calc(var(--tile-radius) - 2px);
  color: inherit; text-decoration: none;
}
.tile-link:hover { color: inherit; }
.tile-icon {
  display: flex; align-items: center; justify-content: center; flex: none;
  width: 54px; height: 54px; margin-bottom: auto;
  border: 2px solid var(--tone-card-text); border-radius: 14px;
  background: var(--tone-card-bg); color: var(--icon, var(--leaf));
  box-shadow: 2px 2px 0 var(--tone-card-text);
}
/* On a Card tile the icon plate is the pale yellow (sun-pale), as in the mockup. */
body:not(.custom-appearance) .tile.tone-card .tile-icon { background: var(--sun-pale); }
.tile-icon .link-logo { width: 28px; height: 28px; border-radius: 6px; }
/* The sprite's brand marks are full-bleed in their box and its outline glyphs are padded, while the
   mockup's glyphs are padded line art (about 18 x 21 px of the 28 px box on a phone, 22 x 26 of 34
   px on a desktop): so they are drawn smaller than an uploaded logo (an <img>) or the inline
   heart, which is the mockup's own drawing and keeps the full size. */
.tile-icon-mark svg.link-logo { width: 22px; height: 22px; }
.tile-icon-line svg.link-logo { width: 24px; height: 24px; }
/* The Shop tile's bag is the mockup's own line drawing (si-shopping-bag-line, stroke 2), in its box:
   28 px on a phone, 34 px on a desktop. A large tile keeps the larger outline-glyph size below. */
.tile-icon-bag svg.link-logo { width: 28px; height: 28px; }
.tile-icon svg.link-logo.mono { color: var(--icon-mono, #000000); }
/* On a phone the arrow is left out and the text takes the whole width (the mockup's too), so
   a subtitle such as "Saturdays · 4 spots left" stays on one line. */
.tile-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding-right: 0; }
/* The ⋯ button covers the tile's top 44 px at the right (10 px down, 32 px high, 2 px shadow). A
   tile with an icon is clear of it: the icon comes first and the text below it. Without one the
   text is the link's first child and, being bottom-aligned, would climb under the button, so it
   keeps that strip free itself (link padding plus this margin: 48 px) and a long text makes the
   tile taller instead. */
.tile-link > .tile-text:first-child { margin-top: 34px; }
.tile-title {
  font-family: var(--font-display); font-weight: 600; font-size: 18px; line-height: 1.15;
  overflow-wrap: anywhere;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden;
}
.size-wide .tile-title { -webkit-line-clamp: 2; line-clamp: 2; }
.size-large .tile-title { font-size: 1.4rem; -webkit-line-clamp: 6; line-clamp: 6; }
.tile-subtitle, .tile-host { font-weight: 700; font-size: 13px; line-height: normal; overflow-wrap: anywhere; }   /* the mockup's: Chrome's rounded Nunito metrics (18 px at 13) */
.tile-host { font-weight: 600; }
/* A Card or Soft tile's second line is the muted green-grey (6:1 on paper and on the soft tints);
   an Accent tile's stays ink. */
body:not(.custom-appearance) .tile:is(.tone-card, .tone-soft) :is(.tile-subtitle, .tile-host) { color: var(--muted); }
.tile-arrow { display: none; position: absolute; right: 18px; bottom: 18px; width: 22px; height: 22px; }
.size-large .tile-icon { width: 60px; height: 60px; }
.size-large .tile-icon .link-logo { width: 36px; height: 36px; }
.size-large .tile-icon-mark svg.link-logo { width: 28px; height: 28px; }
.size-large .tile-icon-line svg.link-logo { width: 30px; height: 30px; }
@media (min-width: 700px) {
  .tile-link { padding: 18px; gap: 12px; }
  .tile-icon { width: clamp(52px, 6.4vw, 68px); height: clamp(52px, 6.4vw, 68px); border-radius: 18px; }
  .tile-icon .link-logo { width: clamp(28px, 3.2vw, 34px); height: clamp(28px, 3.2vw, 34px); border-radius: 8px; }
  .tile-icon-mark svg.link-logo { width: clamp(22px, 2.6vw, 26px); height: clamp(22px, 2.6vw, 26px); }
  .tile-icon-line svg.link-logo { width: clamp(24px, 2.9vw, 28px); height: clamp(24px, 2.9vw, 28px); }
  .tile-icon-bag svg.link-logo { width: clamp(28px, 3.2vw, 34px); height: clamp(28px, 3.2vw, 34px); }
  /* The arrow sits beside the last line only, so only that line keeps its room; a one-word title
     above a subtitle ("Wholesale") then has the tile's whole text width instead of breaking mid-word. */
  .tile-text { padding-right: 0; }
  .tile-text > :last-child { padding-right: 30px; }
  .tile-link > .tile-text:first-child { margin-top: 40px; }
  .tile-title { font-size: clamp(1.1rem, 2.1vw, 1.375rem); }
  .size-large .tile-title { font-size: clamp(1.4rem, 3vw, 1.9rem); }
  .tile-subtitle, .tile-host { font-size: clamp(0.82rem, 1.3vw, 14px); }
  .tile-arrow { display: block; }
  .size-large .tile-icon { width: clamp(64px, 8vw, 84px); height: clamp(64px, 8vw, 84px); }
  .size-large .tile-icon .link-logo { width: clamp(36px, 4.2vw, 44px); height: clamp(36px, 4.2vw, 44px); }
  .size-large .tile-icon-mark svg.link-logo { width: clamp(28px, 3.2vw, 34px); height: clamp(28px, 3.2vw, 34px); }
  .size-large .tile-icon-line svg.link-logo { width: clamp(30px, 3.5vw, 36px); height: clamp(30px, 3.5vw, 36px); }
}

/* The owner's editor preview only (feature 026): an example or pending tile is a <div>, not a link, drawn with a
   dashed 2 px ink outline and a small ink-on-paper mark at its top right (where a real tile's ⋯ sits). Fixed
   colors on purpose: they follow neither the palette nor the tile color nor the tile shape. */
.tile-example { position: relative; cursor: default; outline: 2px dashed #1c1917; outline-offset: -2px; }
.tile-mark {
  position: absolute; top: 8px; right: 8px; padding: 1px 8px;
  border: 1px solid #1c1917; border-radius: 999px; background: #f7fbf1; color: #1c1917;
  font-size: 11px; font-weight: 800; line-height: 1.5; letter-spacing: 0.02em; text-transform: none;
}

/* --- Featured tiles and the cover image (feature 021) --- */
/* A Featured tile is a link tile at Large: a media band (the 16:9 image, or the logo or icon on the cover's
   dots), a badge, then the headline, description and a button. Selectors start with .tile.featured so the
   .size-large rules above never win over these. */
.tile.featured .featured-link {
  flex-direction: column; justify-content: flex-start; gap: 0; padding: 0; height: 100%;
}
.featured-media {
  position: relative; display: flex; align-items: center; justify-content: center; flex: none;
  aspect-ratio: 16 / 9; max-height: 22rem; overflow: hidden;
  border-radius: calc(var(--tile-radius) - 2px) calc(var(--tile-radius) - 2px) 0 0;
  border-bottom: 2px solid var(--tile-edge); background-color: var(--tone-accent-bg);
}
.featured-band {
  background-image: radial-gradient(color-mix(in srgb, var(--tone-accent-text) 28%, transparent) 2.5px, transparent 3px);
  background-size: 18px 18px;
}
.featured-band .tile-icon { margin-bottom: 0; }
/* A failed load shows the band, no stray alt text. */
.featured-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; color: transparent; }
/* Fixed colors on every palette (ink on sun, 10:1); clear of the ⋯ button at the top right. */
.featured-badge {
  position: absolute; top: 12px; left: 12px; max-width: calc(100% - 76px);
  display: inline-flex; align-items: center; gap: 5px; padding: 2px 10px 2px 8px;
  background: var(--sun); color: var(--ink); border: 2px solid var(--ink); border-radius: 999px;
  box-shadow: 2px 2px 0 var(--ink); font-family: var(--font-display); font-weight: 600; font-size: 0.85rem;
}
.featured-badge svg { flex: none; }
.featured-body { display: flex; flex-direction: column; flex: 1; gap: 10px; padding: 14px 16px 16px; min-width: 0; }
.tile.featured .tile-title { font-weight: 700; font-size: 1.25rem; -webkit-line-clamp: 3; line-clamp: 3; }
.featured-description {
  font-size: 0.95rem; line-height: 1.45; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4; line-clamp: 4; overflow: hidden;
}
.featured-cta {
  display: block; margin-top: auto; padding: 11px 18px; text-align: center;
  border: 2px solid var(--tile-edge); border-radius: 999px; box-shadow: 3px 3px 0 var(--tile-edge);
  background: var(--tone-accent-bg); color: var(--tone-accent-text);
  font-family: var(--font-display); font-weight: 600; font-size: 1.05rem;
}
.tile.tone-accent .featured-cta { background: var(--tone-card-bg); color: var(--tone-card-text); }
@media (min-width: 700px) {
  .featured-body { padding: 16px 18px 18px; }
  .tile.featured .tile-title { font-size: clamp(1.25rem, 2.4vw, 1.6rem); }
}
.cover-image { background-color: var(--tone-accent-bg); }
.cover-img { display: block; width: 100%; height: 100%; object-fit: cover; color: transparent; }

/* The ⋯ button sits at the tile's top right, over the tile and beside its link. */
.tile > .link-menu { top: 10px; right: 10px; width: 32px; height: 32px; margin-top: 0; }
.tile .link-menu summary {
  position: relative; width: 32px; height: 32px;
  border: 2px solid var(--tone-card-text);
  background: var(--tone-card-bg); color: var(--tone-card-text);
  box-shadow: 2px 2px 0 var(--tone-card-text);
}
.tile .link-menu summary svg { width: 16px; height: 16px; }
/* The mockup's dots are 2.5 px wide in a 24 px box (a 1 px circle with a 3 px stroke): ours are
   a 2 px radius, so a 1 px stroke brings them to the same size. */
.tile .link-menu summary svg circle { stroke: currentColor; stroke-width: 1; }
/* The drawn circle is the mockup's size; the tap target stays 44 px (an invisible ring around it). */
.tile .link-menu summary::after { content: ""; position: absolute; inset: -6px; border-radius: 50%; }
.tile .link-menu-panel { top: calc(100% + 4px); }
@media (min-width: 700px) {
  .tile > .link-menu { top: 12px; right: 12px; width: 36px; height: 36px; }
  .tile .link-menu summary { width: 36px; height: 36px; }
  .tile .link-menu summary svg { width: 18px; height: 18px; }
  .tile .link-menu summary::after { inset: -4px; }
}
.tile .link-menu summary:hover, .tile .link-menu[open] summary { background: var(--tone-soft-bg); }
.tile .link-menu summary:focus-visible { outline: 3px solid var(--sun); outline-offset: 2px; }

/* A heading: a real <h2> on a small plate, a full row by itself. */
.kind-heading { min-height: 0; border: 0; border-radius: 0; box-shadow: none; background: none; transition: none; }
.kind-heading h2 {
  display: block; width: fit-content; max-width: 100%; margin: 0;
  padding: 4px 14px; font-size: 1.2rem;
  border: 2px solid var(--tone-card-text); border-radius: 999px;
  box-shadow: 2px 2px 0 var(--tone-card-text);
  background: var(--tone-card-bg); color: var(--tone-card-text);
  overflow-wrap: anywhere;
}
.bento-empty {
  width: fit-content; max-width: 100%; margin: 1rem auto 0; padding: 0.3rem 0.9rem;
  border: 2px solid var(--tone-card-text); border-radius: var(--radius-sm);
  background: var(--tone-card-bg); color: var(--tone-card-text);
}

/* The profile tile: a cover band, the photo over its edge, chips beside the photo, then the
   name, bio and icon row. On a phone it is the full first row. */
.profile-tile {
  position: relative; display: flex; flex-direction: column; height: 100%;
  overflow: hidden; border-radius: calc(var(--tile-radius) - 2px);
}
/* The cover is the mockup's 84 px (124 px from 700 px) plus its 2 px bottom border. The chips sit
   beside the photo, which lifts 48 px into the cover, so that row starts at the cover's height
   minus 48 px (38 px on a phone, 78 px from 700 px) and only ever grows downward. Its chips are bottom-aligned with the photo, so the Share button (12 px down on a
   phone, 40 px high and icon-only, a 2 px shadow) is cleared by the chip's own position: a phone
   shows one chip there (the note moves under the name) and its text stops at three lines, so
   the chip starts at about 67 px, below the button's 54 px. tests/unit/test_bento_css.py
   checks the arithmetic. */
.cover {
  flex: none; height: 86px; border-bottom: 2px solid var(--tone-card-text);
  background-color: var(--tone-accent-bg);
}
.cover-pattern {
  background-image: radial-gradient(var(--cover-dot) 2.5px, transparent 3px);
  background-size: 18px 18px;
}
.profile-tile .share-button { position: absolute; top: 12px; right: 12px; z-index: 1; }
.profile-tile-body { display: flex; flex-direction: column; flex: 1; padding: 0 18px 20px; }
.profile-tile-id { position: relative; display: flex; align-items: flex-end; gap: 12px; margin-top: -48px; }
.profile-tile-id .avatar { flex: none; margin: 0; font-size: 44px; line-height: normal; box-shadow: 3px 3px 0 var(--ink); }
/* Theme default: the photo is the deep green with a paper letter (5:1), so it stands out from
   the grass cover behind it. A custom palette keeps the avatar's own colors. */
body:not(.custom-appearance) .profile-tile .avatar { background: var(--leaf); color: var(--paper); }
.profile-tile-id .chips { flex: 1; min-width: 0; padding-bottom: 4px; }
.profile-tile .chip { padding: 3px 10px 3px 7px; font-size: 13px; line-height: normal; }   /* the mockup's: Chrome's rounded Nunito metrics (18 px at 13) */
.profile-tile .chip svg { width: 14px; height: 14px; }
/* A chip's text stops at three lines (it is at most 30 or 40 characters, so only a very narrow
   screen gets there), which keeps the row clear of the Share button. */
.profile-tile .chip span {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden;
}
body:not(.custom-appearance) .profile-tile .chip-note { background: var(--sun-pale); color: var(--ink); }
/* The note chip is drawn twice: beside the photo (with the location) from 1100 px, and on its own
   row under the name line below that. display: none takes the other copy out of the accessibility
   tree, so a screen reader never hears it twice. */
.chips-below { margin-top: 10px; }
@media (min-width: 1100px) { .chips-below { display: none; } }
.profile-tile h1 { margin: 14px 0 0; font-size: 30px; font-weight: 700; line-height: 1.1; letter-spacing: normal; text-shadow: none; overflow-wrap: anywhere; }
.profile-tile .name-line { font-size: 14px; line-height: normal; }   /* the mockup's: Chrome's rounded Nunito metrics (19 px at 14) */
.profile-tile .bio { margin: 10px 0 0; max-width: none; font-size: 15px; line-height: 1.5; text-align: left; overflow-wrap: anywhere; }
.profile-tile .social-icons { justify-content: flex-start; gap: 10px; margin: 0.6rem 0 0; }
.profile-tile .social-icons:last-child { margin-top: auto; padding-top: 16px; }
.profile-tile .social-icon {
  border: 2px solid var(--tone-card-text); background: var(--tone-card-bg);
  box-shadow: 2px 2px 0 var(--tone-card-text);
}
/* The mockup's row is thin line art: 22 px glyphs (X 20) in a 48 px circle, 20 px (X 18) in a 44 px one,
   with the glyph padded in its box (an 18 px Instagram, a 20 x 14 YouTube). A brand mark with no line
   variant is full-bleed, so it is drawn at the line art's visual extent (16 px, 18 px from 700 px). */
.profile-tile .social-icon svg { width: 16px; height: 16px; }
.profile-tile .social-icon-line svg { width: 20px; height: 20px; }
.profile-tile .social-icon-x svg { width: 18px; height: 18px; }
@media (max-width: 699.98px) {
  /* Share is an icon-only 40 px circle; its label stays for screen readers. */
  .profile-tile .share-button { width: 40px; padding: 0; justify-content: center; }
  .profile-tile .share-button span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
/* Both chips beside the photo need a profile tile about 480 px wide (the grid is 4 columns from 700 px,
   so the tile is half the screen less 26 px): until 1100 px (524 px) the note stays under the name
   line, as on a phone, instead of the two chips stacking up over the cover's edge. */
@media (max-width: 1099.98px) {
  .profile-tile-id .chip-note, .profile-tile-id .chips:not(:has(.chip-location)) { display: none; }
}
@media (min-width: 700px) {
  .cover { height: 126px; }
  .cover-pattern { background-size: 20px 20px; }
  .profile-tile .share-button { top: 16px; right: 16px; }
  .profile-tile-body { padding: 0 28px 26px; }
  .profile-tile-id { gap: 14px; }
  .profile-tile-id .avatar { font-size: 46px; }
  .profile-tile .chip { padding: 4px 12px 4px 8px; font-size: 14px; }
  .profile-tile .chip svg { width: 15px; height: 15px; }
  .profile-tile h1 { margin-top: 16px; font-size: 36px; }
  .profile-tile .name-line { font-size: 16px; }
  .profile-tile .bio { margin-top: 12px; font-size: 17px; }
  .profile-tile .social-icons { gap: 12px; }
  .profile-tile .social-icons:last-child { padding-top: 18px; }
  .profile-tile .social-icon { width: 48px; height: 48px; }
  .profile-tile .social-icon svg { width: 18px; height: 18px; }
  .profile-tile .social-icon-line svg { width: 22px; height: 22px; }
  .profile-tile .social-icon-x svg { width: 20px; height: 20px; }
}

/* The page footer. Phone: a pill with the badge and "Make your own page", and a separate smaller
   Report pill under it. From 700 px: one pill with a divider between the two. Terms · Privacy is
   a quiet line under either. */
.made-with.profile-footer {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  margin: 28px auto 0; padding: 0;
  background: none; border: 0; border-radius: 0;
  font-weight: 400;
}
.made-with-row { display: flex; flex-direction: column; align-items: center; gap: 10px; max-width: 100%; }
.made-with-brand {
  display: flex; align-items: center; gap: 10px; max-width: 100%;
  padding: 7px 18px 7px 8px;
  background: color-mix(in srgb, var(--paper) 94%, transparent);
  border: 2px solid var(--ink); border-radius: 999px; box-shadow: 2px 2px 0 var(--ink);
}
.made-with-brand img { flex: none; display: block; width: 30px; height: 30px; }
.made-with-cta { font-family: var(--font-display); font-weight: 600; font-size: 16px; line-height: normal; color: var(--forest); text-align: left; }
.profile-footer a { text-decoration: none; }
.made-with-divider { display: none; flex: none; width: 2px; height: 22px; background: var(--rule); }
.profile-footer .report-footer {
  display: inline-block; margin: 0; padding: 4px 14px; border-radius: 999px;
  background: color-mix(in srgb, var(--paper) 94%, transparent);
  font-weight: 700; font-size: 14px; line-height: normal; color: var(--muted);   /* 4 + 19 + 4: the mockup's 27 px pill */
}
.profile-footer .legal-links {
  margin: 0; padding: 2px 10px; border-radius: 999px;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  font-size: 13px; font-weight: 600; line-height: 1.4; color: var(--muted);
}
body:not(.custom-appearance) .profile-footer .legal-links a { color: var(--muted); }
@media (min-width: 700px) {
  .made-with.profile-footer { margin-top: 36px; }
  .made-with-row {
    flex-direction: row; gap: 16px; padding: 8px 22px 8px 10px;
    background: color-mix(in srgb, var(--paper) 94%, transparent);
    border: 2px solid var(--ink); border-radius: 999px; box-shadow: 2px 2px 0 var(--ink);
  }
  .made-with-brand { gap: 16px; padding: 0; background: none; border: 0; box-shadow: none; }
  .made-with-brand img { width: 34px; height: 34px; }
  .made-with-cta { font-size: 17px; }
  .made-with-divider { display: block; }
  .profile-footer .report-footer { padding: 0; background: none; font-size: 15px; }
}

/* --- Video and music tiles (feature 022) --- */
/* A link out with a thumbnail, never an embed. Wide: thumbnail on the left (full height, the item's shape), text on
   the right; Large: thumbnail on top, text below; Small: the thumbnail fills the tile and the text sits on a dark
   band. No hex colors except #fff and rgba(0,0,0,..) on the image band. */
.media-link { position: relative; flex-direction: row; align-items: stretch; justify-content: flex-start; gap: 0; padding: 0; overflow: hidden; }
.media-thumb {
  position: relative; display: block; flex: none; overflow: hidden; background: var(--tone-soft-bg); color: var(--tone-soft-text);
}
.media-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; color: transparent; }
.media-placeholder { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.media-placeholder svg { width: 40%; height: 40%; }
.media-play {
  position: absolute; top: 50%; left: 50%; display: flex; align-items: center; justify-content: center;
  width: 56px; height: 40px; transform: translate(-50%, -50%);
  border: 2px solid #fff; border-radius: 12px; background: var(--leaf); color: #fff; box-shadow: 2px 2px 0 var(--tile-edge);
}
.media-link .tile-text { justify-content: center; flex: 1; padding: 14px 44px 14px 14px; }
.media-label { display: flex; align-items: center; gap: 6px; }
.media-provider { flex: none; width: 16px; height: 16px; }
.media-provider.mono { color: var(--icon-mono, #000000); }
.tile.kind-media .tile-link > .tile-text:first-child { margin-top: 0; }
.tile.kind-media .tile-text > :last-child { padding-right: 0; }
.media-landscape .media-thumb { aspect-ratio: 16 / 9; }
.media-square .media-thumb { aspect-ratio: 1 / 1; }
.media-vertical .media-thumb { aspect-ratio: 9 / 16; }
/* Wide (and any size on the row layout) */
.size-wide .media-thumb { align-self: stretch; height: 100%; max-width: 58%; }
/* Large: thumbnail on top at full width; a square or vertical item is capped and cropped. */
.size-large .media-link { flex-direction: column; }
.size-large .media-thumb { width: 100%; max-width: none; aspect-ratio: 16 / 9; }
.size-large.media-square .media-thumb, .size-large.media-vertical .media-thumb { aspect-ratio: auto; height: 62%; }
.size-large .media-link .tile-text { flex: none; padding: 14px 16px 16px; }
/* Small: the thumbnail fills the tile, the text on a bottom band */
.size-small .media-thumb { position: absolute; inset: 0; width: 100%; max-width: none; aspect-ratio: auto; height: 100%; }
.size-small .media-link .tile-text {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 28px 12px 12px; flex: none; justify-content: flex-end;
  background: linear-gradient(to top, rgba(0, 0, 0, .8), transparent); color: #fff;
}
.size-small .media-link .tile-title { -webkit-line-clamp: 2; line-clamp: 2; font-size: 15px; }
body:not(.custom-appearance) .tile.kind-media.size-small .tile-subtitle { color: #fff; }
.size-small .media-play { top: 40%; width: 44px; height: 32px; }
@media (min-width: 700px) {
  .media-link .tile-text { padding: 18px 48px 18px 18px; }
  .size-large .media-link .tile-text { padding: 16px 18px 18px; }
  .size-small .media-link .tile-text { padding: 32px 14px 14px; }
}

/* Tile shapes (Rounded is the default; the body class comes from the creator's choice). The
   Outline shape is see-through with the page's text color; the profile tile and headings keep
   their plates. */
.btn-outline .tile:not(.kind-profile, .kind-heading) {
  background: transparent; color: inherit; border-color: currentColor; box-shadow: none;
}
.btn-outline .tile:not(.kind-profile, .kind-heading):hover { background: rgba(127, 127, 127, 0.12); box-shadow: none; }
.btn-outline .tile-icon { box-shadow: none; }

/* Fonts (Theme default with a font class, or a custom palette) reach the bento text too. */
.custom-appearance :is(.tile-title, .kind-heading h2, .chip, .share-button) { font-family: var(--page-font); }
:is(.font-serif, .font-mono, .font-humanist) :is(.tile-title, .kind-heading h2, .chip, .share-button) { font-family: var(--page-font); }

@media (prefers-reduced-motion: reduce) {
  .tile { transition: none; }
}


/* --- Feature 023: Account (login "Forgot password?", forgot / reset / goodbye pages) ------ */

/* The Password label with "Forgot password?" at its right end (login). */
/* Login's password field: the label and "Forgot password?" share the first row, the input spans the
   second; in the DOM the link comes after the input, so Tab goes from Email to Password. */
.password-field {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 12px; align-items: baseline;
  margin-top: 0.8rem;
}
.password-field label { grid-area: 1 / 1; margin: 0 0 0.3rem; }
.password-field input { grid-area: 2 / 1 / 3 / 3; }
.password-field a {
  grid-area: 1 / 2;
  font-size: 0.92rem; font-weight: 600; color: var(--forest); text-underline-offset: 0.15em;
  padding: 11px 0; margin: -11px 0; /* a 44px target */
}
/* The new-password field of the reset page: the input and its Show / Hide button. */
.password-row { display: flex; align-items: stretch; gap: 8px; }
.password-row input { flex: 1; min-width: 0; }
.password-row input::-ms-reveal, .password-row input::-ms-clear { display: none; }
.password-row ~ .hint { margin: 4px 0 0; }
.show-password {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  height: 47.2px; padding: 8px 15.2px;
}
/* ``.show-password`` sets display, which would beat the UA's [hidden] rule and show a dead button to
   visitors without JavaScript. */
.show-password[hidden] { display: none; }
/* "Send another link": a full-width secondary button (the look of ``a.button.google``). */
.auth-card button.secondary-block {
  display: block; width: 100%; min-height: 44px; margin: 0; padding: 8px 15.2px; text-align: center;
}
.auth-card .card-note { color: var(--muted); font-size: 0.92rem; margin: 12px 0 14.72px; }
/* The goodbye headline is an H1 (the card has none). */
.auth-hero h1.auth-headline { margin: 8px auto 4px; letter-spacing: normal; }
.goodbye-card > p:first-child { margin: 0; }
/* Footer links under the cards ("Back to log in", "Create a new page", ...): a 44px target. */
.auth-card p.text-backing a { display: inline-block; padding: 11px 0; margin: -11px 0; }
/* A long email address ("For {email}.", "Check your email", the goodbye page) breaks inside the card. */
.auth-card p { overflow-wrap: anywhere; }

/* --- 029 blocks (Bento): Text, Image, Gallery, Event, Location, Divider, Latest videos -------------------------
   Same tile look as the link tiles (2 px outline, hard shadow, tones). Colours are the page's tokens, so a custom
   palette and every theme carry over. Class names start with block-; tile-mark and tile-example are 026's. */
.tile.block-static:hover { box-shadow: 4px 4px 0 var(--tile-edge); }   /* nothing to tap: no lift */

/* ENH-004: custom edges never change the automatically readable text colors. */
body.public.has-custom-border { --tile-edge: var(--custom-border); }
.public.has-custom-border .profile-card { border: 2px solid var(--custom-border); box-shadow: 4px 4px 0 var(--custom-border); }
.public.has-custom-border .public-link,
.public.has-custom-border .public-link:hover { border-color: var(--custom-border); box-shadow: 3px 3px 0 var(--custom-border); }
.tile.kind-text, .tile.kind-feed { min-height: 0; }
.block-title, .block-heading, .block-day, .block-video-title { font-family: var(--font-display); font-weight: 600; overflow-wrap: anywhere; }
.custom-appearance :is(.block-title, .block-heading, .block-day, .block-video-title) { font-family: var(--page-font); }

/* Text: left-aligned, the menu button's corner left free. */
.block-text { padding: 20px 56px 20px 18px; font-size: 1rem; line-height: 1.55; overflow-wrap: anywhere; }
.block-text > :first-child { margin-top: 0; }
.block-text > :last-child { margin-bottom: 0; }
.block-text p { margin: 0 0 0.6em; }
.block-text ul, .block-text ol { margin: 0.6em 0 0; padding-left: 1.3em; }
.block-text a { color: inherit; font-weight: 700; text-decoration: underline; text-underline-offset: 2px; }
@media (min-width: 700px) { .block-text { padding: 22px 64px 22px 24px; font-size: 1.0625rem; } }

/* Image: the picture fills the tile, cropped from the centre (Small and Large are square, Wide is 2:1, by the row
   classes); the caption sits under it. */
.kind-image { display: flex; overflow: hidden; }
.block-figure { display: flex; flex: 1 1 auto; flex-direction: column; margin: 0; min-width: 0; }
.block-pic { position: relative; display: block; flex: 1 1 auto; min-height: 0; overflow: hidden; color: inherit; background: var(--tint); }
.block-pic img, .block-pic .block-ph { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; object-position: center; }
.block-caption {
  flex: none; padding: 8px 12px 10px; border-top: 2px solid var(--tile-edge);
  font-weight: 700; font-size: 0.875rem; line-height: 1.35; overflow-wrap: anywhere;
}
.block-ph { display: block; background: color-mix(in srgb, var(--tone-card-text) 12%, var(--tint)); }

/* Scrolling rows (Gallery, Latest videos): focusable regions that snap; no script. */
.block-scroll { display: flex; gap: 10px; margin: 0; padding: 0 0 4px; list-style: none; overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth; scrollbar-width: none; border-radius: 12px; }
.block-scroll::-webkit-scrollbar { display: none; }
.block-scroll:focus-visible { outline: 3px solid var(--sun); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .block-scroll { scroll-behavior: auto; } }
.block-heading { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; padding-right: 40px; font-size: 1.125rem; line-height: 1.2; }
.block-count { font-family: var(--font-body); font-weight: 700; font-size: 0.8125rem; color: var(--muted); }

/* Gallery: about 1.6 pictures show on a phone, two on a desktop. */
.block-gallery { padding: 14px 14px 12px; }
.block-slides > li { flex: 0 0 62%; aspect-ratio: 1 / 1; position: relative; box-sizing: border-box; overflow: hidden; scroll-snap-align: start; border: 2px solid var(--tile-edge); border-radius: 12px; background: var(--tint); }
.block-slides img, .block-slides .block-ph { display: block; width: 100%; height: 100%; object-fit: cover; }
@media (min-width: 700px) { .block-slides > li { flex-basis: calc(50% - 5px); } }

/* Event: a date badge and the text, then Add to calendar under them. */
.kind-event { display: flex; flex-direction: column; }
.block-event { display: flex; flex: 1 1 auto; gap: 14px; padding: 18px 56px 4px 18px; color: inherit; text-decoration: none; }
.block-date { flex: none; display: block; width: 58px; align-self: flex-start; box-sizing: border-box; overflow: hidden; text-align: center; border: 2px solid var(--tile-edge); border-radius: 12px; box-shadow: 2px 2px 0 var(--tile-edge); background: var(--tone-card-bg); color: var(--tone-card-text); }
.block-month { display: block; padding: 2px 0; border-bottom: 2px solid var(--tile-edge); background: var(--tone-accent-bg); color: var(--tone-accent-text); font-weight: 800; font-size: 0.75rem; letter-spacing: 0.08em; text-transform: uppercase; }
.block-day { display: block; padding: 3px 0 5px; font-weight: 700; font-size: 1.5rem; line-height: 1; }
.block-event-text, .block-location-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.block-event .block-title { font-size: 1.25rem; line-height: 1.15; }
.block-when { font-weight: 800; font-size: 0.875rem; line-height: 1.4; }
.block-place { font-weight: 700; font-size: 0.84rem; line-height: 1.4; color: var(--muted); overflow-wrap: anywhere; }
.block-relative { display: inline-flex; align-items: center; gap: 5px; width: fit-content; margin-top: 4px; padding: 1px 9px 1px 7px; border: 2px solid var(--tile-edge); border-radius: 999px; background: var(--sun-pale); color: var(--ink); font-weight: 800; font-size: 0.8125rem; line-height: 1.4; }
.block-event-cal { padding: 0 14px 4px 90px; }
.block-event-cal a { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; font-weight: 700; font-size: 0.9375rem; color: inherit; text-decoration: underline; text-underline-offset: 2px; }

/* Location: a pin plate, the name, address and note, and the "Open in Maps" cue at the bottom. */
.block-location { display: flex; flex-direction: column; gap: 8px; box-sizing: border-box; height: 100%; padding: 18px; color: inherit; text-decoration: none; }
.block-pin { display: flex; align-items: center; justify-content: center; width: 46px; height: 46px; box-sizing: border-box; border: 2px solid var(--tile-edge); border-radius: 12px; box-shadow: 2px 2px 0 var(--tile-edge); background: var(--sun-pale); color: var(--leaf); }
.block-location .block-title { font-size: 1.0625rem; line-height: 1.15; }
.block-address { font-style: normal; font-size: 0.84rem; line-height: 1.4; overflow-wrap: anywhere; }
.block-note { font-weight: 700; font-size: 0.8125rem; line-height: 1.4; }
.block-open { display: inline-flex; align-items: center; gap: 4px; margin-top: auto; font-weight: 800; font-size: 0.84rem; }

/* Divider: a thin line or plain space, a full row, nothing to tap. */
.block-divider { display: flex; align-items: center; min-height: 0; padding: 6px 0; list-style: none; }
.block-divider.style-space { height: 28px; padding: 0; }
.block-rule { flex: 1 1 auto; height: 0; border-top: 2px solid var(--tile-edge); opacity: 0.45; }

/* Latest videos: a heading row with More on YouTube, then 3, 4 or (6 as 2 x 3) across; a phone swipes ~1.5 at a time. */
.block-feed { padding: 16px 16px 14px; }
.block-feed-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0 12px; margin: 0 0 8px; padding-right: 44px; }
.block-feed-head .block-heading { margin: 0; padding: 0; font-size: 1.15rem; }
.block-yt { display: flex; color: var(--leaf); }
.block-more { display: inline-flex; align-items: center; gap: 5px; min-height: 44px; font-weight: 700; font-size: 0.9375rem; color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.block-videos { gap: 14px; }
.block-videos > li { flex: 0 0 64%; min-width: 0; scroll-snap-align: start; }
.block-videos a { display: block; color: inherit; text-decoration: none; border-radius: 10px; }
.block-thumb { position: relative; display: block; width: 100%; aspect-ratio: 16 / 9; box-sizing: border-box; overflow: hidden; border: 2px solid var(--tile-edge); border-radius: 10px; background: var(--tint); }
.block-thumb img, .block-thumb .block-ph { display: block; width: 100%; height: 100%; object-fit: cover; }
.block-video-title { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; margin-top: 8px; font-size: 0.95rem; line-height: 1.25; }
.block-ago { display: block; margin-top: 3px; font-weight: 700; font-size: 0.8125rem; color: var(--muted); }
@media (min-width: 700px) {
  .block-feed { padding: 18px 22px; }
  .block-videos { display: grid; gap: 18px; overflow: visible; }
  .block-videos.feed-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .block-videos.feed-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .block-videos.feed-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .block-videos.feed-6 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .block-video-title { font-size: 1rem; }
}

/* --- 029 Classic rows: the same pieces as full-width rows of the link list ---------------------------------- */
.block-classic { min-height: 0; }
.block-classic .block-text { font-size: 1rem; }
/* Image: the full row width, cropped to at most 4:5, caption under it. */
.block-classic .block-pic { flex: none; aspect-ratio: 4 / 5; }
.block-classic .block-pic img { max-height: none; }
/* Gallery: about 1.2 pictures show on a phone, two from 700 px. */
.block-classic .block-slides > li { flex-basis: 82%; }
@media (min-width: 700px) { .block-classic .block-slides > li { flex-basis: calc(50% - 5px); } }
/* Latest videos: one row per video, thumbnail in the logo slot, never a grid. */
.block-classic .block-videos { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; overflow: visible; }
.block-classic .block-videos > li { flex: none; }
.block-classic .block-videos a { display: grid; grid-template-columns: 96px minmax(0, 1fr); grid-template-rows: auto auto; column-gap: 12px; align-items: center; align-content: center; }
.block-classic .block-thumb { grid-row: 1 / span 2; }
.block-classic .block-video-title { margin-top: 0; align-self: end; }
.block-classic .block-ago { margin-top: 0; align-self: start; }
.block-classic .block-feed, .block-classic .block-feed-head { padding-top: 14px; }
.block-classic .block-feed-head { padding-top: 0; }
/* Event and Location are already one row: keep the date and pin plates, drop the tall stacking. */
.block-classic .block-location { flex-direction: row; align-items: flex-start; gap: 14px; padding-right: 56px; }
.block-classic .block-location .block-open { position: absolute; right: 14px; bottom: 12px; margin: 0; }
.block-classic .block-location-text { padding-bottom: 20px; }

/* 032: Classic YouTube cards reuse media markup without Bento size rules. */
.media-classic { min-height: 0; }
.media-classic .media-link { flex-direction: column; }
.media-classic .media-thumb { width: 100%; aspect-ratio: 16 / 9; }
.media-classic .tile-text { padding: 14px 44px 14px 14px; }

/* --- Page background image (feature 034, Pro and Max) -------------------------------------
   A fixed layer (background-attachment: fixed is ignored on iOS) over the image's own average
   color, which shows first; the wash is that color too, so the text color chosen for it holds at
   every readability level. Colors are validated hex values from the server; no creator CSS. */
body.public.has-bg-image { background: var(--bg-wash); color: var(--page-text); }
body.public.has-bg-image::before { content: none; background: none; }
html:has(body.has-bg-image) { background: var(--bg-wash); }
.page-bg { position: fixed; inset: 0; z-index: -1; overflow: hidden; pointer-events: none; }
.page-bg picture { display: contents; }
.page-bg img { display: block; width: 100%; height: 100%; object-fit: cover; }
.page-bg::after { content: ""; position: absolute; inset: 0; background: var(--bg-wash); opacity: 0; }
.bg-dim-light .page-bg::after { opacity: 0.35; }
.bg-dim-strong .page-bg::after { opacity: 0.62; }
/* The footer pills keep their paper fill and the theme's text colours over any image (a custom palette's
   --page-text is for the image, not for paper). */
.has-bg-image .made-with-brand, .has-bg-image .profile-footer .report-footer, .has-bg-image .profile-footer .legal-links { background: var(--paper); }
.has-bg-image .made-with a.made-with-cta { color: var(--forest); }
.has-bg-image .profile-footer .report-footer, .has-bg-image .profile-footer .legal-links { color: var(--muted); }
.has-bg-image .profile-footer .report-footer:hover, .has-bg-image .profile-footer .legal-links a { color: var(--muted); }
@media (min-width: 700px) { .has-bg-image .made-with-row { background: var(--paper); } }
/* See-through cards: the card color at 55 / 70 / 82 % by readability level, over a blur. */
.bg-glass { --glass: 55%; }
.bg-glass.bg-dim-light { --glass: 70%; }
.bg-glass.bg-dim-strong { --glass: 82%; }
.bg-glass :is(.profile-card, .tile:not(.kind-heading), .kind-heading h2) {
  background: color-mix(in srgb, var(--tone-card-bg) var(--glass), transparent);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
}
.bg-glass .tile.tone-accent { background: color-mix(in srgb, var(--tone-accent-bg) calc(var(--glass) + 8%), transparent); }
.bg-glass .tile.tone-soft { background: color-mix(in srgb, var(--tone-soft-bg) var(--glass), transparent); }
.bg-glass :is(.name-line, .link-subtitle, .tile-subtitle, .tile-host) { color: var(--tone-card-text) !important; }
.bg-glass .profile-header h1 { text-shadow: none; }
@supports not (backdrop-filter: blur(1px)) {
  .bg-glass { --glass: 65%; }
  .bg-glass.bg-dim-light { --glass: 80%; }
  .bg-glass.bg-dim-strong { --glass: 92%; }
}
