/* ItemTree submission page. Fonts are self hosted under /fonts (SIL Open Font Licence, the
   licence files sit beside them). No third party request of any kind. */

@font-face {
  font-family: "Cinzel";
  src: url("/fonts/Cinzel-wght.ttf") format("truetype");
  font-weight: 500 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Spectral";
  src: url("/fonts/Spectral-Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Spectral";
  src: url("/fonts/Spectral-Italic.ttf") format("truetype");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: "JetBrains Mono";
  src: url("/fonts/JetBrainsMono-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  --surface: #070806;
  --body: #ece2cb;
  --text: #d9cfb6;
  --sub: #b8ad93;
  --muted: #7d7560;
  --title: #f3d585;
  --gold: #d9b26a;
  --link: #e9c46a;
  --link-hover: #fbe3a0;
  --soon: #b9a16c;
  --foot: #a08b5e;
  --paste-text: #e6dcc2;
  --paste-bg: #0a0a08;
  --note-text: #cfd3bd;
  --lock: #9fbf74;
  --refuse: #e08a6a;
  --button-text: #1a1408;
  --line: rgba(217, 178, 106, 0.2);
  --line-mid: rgba(217, 178, 106, 0.4);
  --line-strong: rgba(217, 178, 106, 0.55);
  --serif: "Spectral", Georgia, serif;
  --display: "Cinzel", Georgia, serif;
  --mono: "JetBrains Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  background: var(--surface);
}

body {
  position: relative;
  min-height: 100vh;
  overflow-x: hidden;
  color: var(--body);
  font-family: var(--serif);
  font-size: 16px;
  line-height: 1.5;
}

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

/* The blurred background picture and the shade over it, behind everything. */
.backdrop {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.backdrop::before {
  content: "";
  position: absolute;
  inset: -60px;
  background: url("/bg.png") center / cover no-repeat;
  filter: blur(36px) saturate(1.15);
  opacity: 0.75;
}

.backdrop::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at 30% 20%, rgba(40, 60, 28, 0.35), rgba(6, 7, 5, 0.92) 70%);
}


/* The sizes are mobile first, with min-width queries only, so every window width (fractional
   ones under browser zoom included) matches exactly one layout. The base rules below are the
   phone layout: no frame rules and no feature rows, the logo, the text and the panel stacked
   edge to edge with a 16px gutter. From 600px the frame returns at about 85 percent of the full
   sizes, still stacked; from 740px the same reduced sizes sit in two columns and the feature rows
   return; from 1101px everything takes the design's full sizes. */

[hidden] { display: none !important; }

/* The two thin gold rules framing the page. */
.frame {
  display: none;
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.frame::before,
.frame::after {
  content: "";
  position: absolute;
}

.frame::before {
  inset: 14px;
  border: 1px solid rgba(217, 178, 106, 0.45);
  border-radius: 4px;
}

.frame::after {
  inset: 19px;
  border: 1px solid rgba(217, 178, 106, 0.18);
  border-radius: 2px;
}

.layout {
  position: relative;
  max-width: 1440px;
  /* The footer row's height comes off, so the page and its two store links fit one screen. */
  min-height: calc(100vh - 48px);
  margin: 0 auto;
  padding: 24px 16px;
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  align-items: center;
  /* Stacked, the rows sit together in the middle; stretched rows would open a band between the
     text and the panel. */
  align-content: center;
}

/* Left: the logo, the title and the four features. */
.hero {
  flex: 1 1 100%;
  max-width: none;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

/* logo.png has a clear margin of 15.2 percent of its width each side of the shield (x 78 to 433
   of 512). Where the hero is left aligned the logo is pulled left by that margin so the shield's
   edge sits on the text's edge: width and margin percentages both resolve against the hero's
   width, so the margin is computed from the same expression as the width. On phones it is
   centred. */
.logo {
  display: block;
  width: min(240px, 70%);
  height: auto;
  margin: 0 auto;
}

.hero-text {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.eyebrow {
  margin: 0;
  font-family: var(--display);
  font-size: 11px;
  letter-spacing: 0.24em;
  color: var(--gold);
}

/* The title wraps to two lines at most ("Help make / ItemTree better!", a no-break space holding
   the last two words together) or sits on one. "ItemTree better!" is about 9 em wide in Cinzel at
   weight 600, so each step's largest size keeps 9 em inside its narrowest column: phones and the
   stacked 600px step (the full content width), 32px in the 300px two column hero, 44px in the
   420px wide hero. */
h1 {
  margin: 0;
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(26px, 5.4vw, 40px);
  line-height: 1.1;
  color: var(--title);
  text-wrap: balance;
}

/* Stacked, the text fills the content width inside the gutter; the measure applies in two columns. */
.lead {
  margin: 0;
  max-width: none;
  font-size: 16px;
  line-height: 1.55;
  color: var(--text);
  text-wrap: pretty;
}

.features {
  display: none;
  margin: 0;
  padding: 6px 0 0;
  list-style: none;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px 18px;
  border-top: 1px solid var(--line);
}

.features li {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  line-height: 1.35;
  color: var(--text);
}

.features li:nth-child(-n + 2) { padding-top: 12px; }

.features img {
  flex: none;
  width: 40px;
  height: 40px;
  object-fit: contain;
}

.features em { font-style: italic; color: var(--soon); }

/* Right: the panel holding the form, or the thanks after a send. */
.panel {
  flex: 1 1 100%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  padding: 6px;
  background: linear-gradient(180deg, rgba(26, 24, 18, 0.92), rgba(14, 13, 10, 0.94));
  border: 1px solid var(--line-strong);
  border-radius: 6px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 230, 170, 0.08);
}

.panel-inner {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  padding: 18px 16px;
  border: 1px solid var(--line);
  border-radius: 3px;
}

/* The two tabs at the top of the panel, shown by the script: the active one gold. Without the
   script the row stays hidden and both forms show, one under the other. */
.tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 18px;
}

.tab {
  flex: 1 1 0;
  min-width: 0;
  padding: 10px 12px;
  font-family: var(--display);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sub);
  background: transparent;
  border: 1px solid var(--line-mid);
  border-radius: 3px;
  cursor: pointer;
}

.tab:hover { color: var(--link-hover); background: rgba(217, 178, 106, 0.08); }

.tab[aria-selected="true"] {
  color: var(--button-text);
  background: linear-gradient(180deg, #f3d585, #c99a45);
  border-color: #f6dc95;
}

.tab:focus-visible {
  outline: 2px solid var(--link);
  outline-offset: 3px;
}

.pane {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* No script: the bug form sits under the share form, set apart by a rule. */
.tabs[hidden] ~ .pane + .pane {
  margin-top: 28px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
}

h2 {
  margin: 0;
  font-family: var(--display);
  font-weight: 600;
  font-size: 20px;
  color: var(--title);
}

.share {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.share-head {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.sub {
  margin: 0;
  font-size: 16px;
  color: var(--sub);
}

.paste {
  flex: none;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

textarea {
  flex: 1;
  display: block;
  width: 100%;
  min-height: 180px;
  padding: 14px 16px;
  resize: none;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.5;
  color: var(--paste-text);
  background: var(--paste-bg);
  border: 1px solid var(--line-mid);
  border-radius: 3px;
  outline: none;
  word-break: break-all;
}

textarea:focus {
  border-color: var(--link);
  box-shadow: 0 0 0 3px rgba(233, 196, 106, 0.15);
}

/* The line under the box: the empty hint or a refusal on the left, the byte count on the right. */
.status {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  min-height: 20px;
  font-size: 14px;
}

.status p { margin: 0; }

.waiting {
  display: none;
  color: var(--muted);
}

/* Shown while nothing is pasted. The box is required, so it is :invalid exactly while empty; this
   works with or without script. */
textarea:invalid + .status .waiting { display: block; }

.error { color: var(--refuse); }

.status .size {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
}

.note {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 14px 16px;
  background: rgba(60, 80, 40, 0.18);
  border: 1px solid rgba(140, 170, 100, 0.2);
  border-radius: 3px;
}

.note p {
  margin: 0;
  font-size: 15px;
  line-height: 1.5;
  color: var(--note-text);
}

.lock {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 3px;
}

.lock .shackle {
  width: 10px;
  height: 8px;
  border: 2px solid var(--lock);
  border-bottom: none;
  border-radius: 6px 6px 0 0;
}

.lock .body {
  width: 16px;
  height: 11px;
  background: var(--lock);
  border-radius: 2px;
}

.submit {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 16px;
  font-family: var(--display);
  font-weight: 700;
  font-size: 16px;
  letter-spacing: 0.16em;
  color: var(--button-text);
  background: linear-gradient(180deg, #f3d585, #c99a45);
  border: 1px solid #f6dc95;
  border-radius: 3px;
  box-shadow: 0 6px 20px rgba(201, 154, 69, 0.25);
  cursor: pointer;
}

.submit:hover { filter: brightness(1.08); }
.submit:active { transform: translateY(1px); }

.submit:focus-visible,
.again:focus-visible {
  outline: 2px solid var(--link);
  outline-offset: 3px;
}

/* The design's disabled look: set by the script while the box is empty. */
.submit:disabled:not(.sending) {
  color: #6f6550;
  background: rgba(217, 178, 106, 0.06);
  border-color: rgba(217, 178, 106, 0.25);
  box-shadow: none;
  filter: none;
  transform: none;
  cursor: not-allowed;
}

/* No script: the same look read from the empty box. The text area is required, so the browser
   refuses an empty send either way. */
.share:has(textarea:invalid) .submit {
  color: #6f6550;
  background: rgba(217, 178, 106, 0.06);
  border-color: rgba(217, 178, 106, 0.25);
  box-shadow: none;
  filter: none;
  transform: none;
  cursor: not-allowed;
}

/* While sending: the button keeps its gold, with a small spinner before the label. */
.submit.sending {
  filter: none;
  transform: none;
  cursor: progress;
}

.submit.sending::before {
  content: "";
  width: 14px;
  height: 14px;
  border: 2px solid rgba(26, 20, 8, 0.3);
  border-top-color: var(--button-text);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* The thanks in place, and the result pages the app answers to a send without the script. */
.result {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 24px 0;
  text-align: center;
}

.result-icon {
  width: 84px;
  height: 84px;
  object-fit: contain;
}

.result h2 { font-size: 22px; }
.result h2:focus { outline: none; }

.result p {
  margin: 0;
  max-width: 26em;
  font-size: 18px;
  line-height: 1.55;
  color: var(--text);
}

.result.refused h2 { color: var(--refuse); }

.again {
  margin-top: 8px;
  padding: 12px 22px;
  font-family: var(--display);
  font-size: 14px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--link);
  text-decoration: none;
  background: transparent;
  border: 1px solid rgba(217, 178, 106, 0.5);
  border-radius: 3px;
  cursor: pointer;
}

.again:hover {
  color: var(--link);
  background: rgba(217, 178, 106, 0.1);
}

/* The small row under the page: the store links, muted gold. */
.site-foot {
  position: relative;
  display: flex;
  justify-content: center;
  gap: 24px;
  padding: 0 16px 28px;
  font-size: 14px;
  line-height: 20px;
}

.site-foot a { color: var(--foot); }
.site-foot a:hover { color: var(--link-hover); }

.hidden-label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* From 600px: the frame returns and the reduced sizes apply, still stacked, the feature rows still
   hidden, the text filling the width and the same 24px between the text and the panel. */
@media (min-width: 600px) {
  .frame { display: block; }
  .layout { padding: 32px; gap: 24px; }
  .hero { gap: 22px; }
  .logo { width: min(260px, 80%); margin: 0 0 0 calc(min(260px, 80%) * -0.152); }
  .hero-text { gap: 12px; }
  .panel-inner { padding: 22px; }
  .sub { font-size: 14px; }
  textarea { min-height: 150px; font-size: 12px; }
  .note { padding: 12px 14px; }
  .note p { font-size: 13.5px; }
  .submit { padding: 13px; font-size: 14px; }
  .result { padding: 28px 8px; gap: 14px; }
  .result-icon { width: 72px; height: 72px; }
  .result h2 { font-size: 24px; }
  .result p { font-size: 16px; }
}

/* From 740px: the same reduced sizes in an explicit two column grid that cannot wrap, so the
   feature rows (shown only here and wider) always sit beside the panel. */
@media (min-width: 740px) {
  .layout {
    display: grid;
    grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
    gap: 32px;
  }
  .features { display: grid; }
  h1 { font-size: clamp(26px, 3.8vw, 32px); }
  .lead { max-width: 34em; }
}

/* From 1101px: the design's full sizes, and the panel keeps its tall shape with the text area
   filling it. */
@media (min-width: 1101px) {
  .layout {
    padding: clamp(32px, 4vw, 48px) clamp(24px, 5vw, 56px);
    gap: clamp(36px, 6vw, 80px);
  }
  .layout { grid-template-columns: minmax(0, 420px) minmax(min(100%, 420px), 1fr); }
  .hero { gap: 28px; }
  .logo { width: min(320px, 80%); margin: 0 0 0 calc(min(320px, 80%) * -0.152); }
  .hero-text { gap: 14px; }
  .eyebrow { font-size: 13px; }
  h1 { font-size: clamp(32px, 4.4vw, 44px); }
  .lead { font-size: 19px; }
  .features { gap: 14px 22px; }
  .features li { font-size: 16px; gap: 12px; }
  .features li:nth-child(-n + 2) { padding-top: 14px; }
  .features img { width: 46px; height: 46px; }
  .panel {
    height: calc(100vh - 96px);
    max-height: 800px;
    min-height: 560px;
  }
  /* No script: both forms show, so the panel grows to hold them. */
  .panel:has(.tabs[hidden]) { height: auto; max-height: none; }
  .panel-inner { padding: clamp(22px, 3.4vw, 36px); }
  .share { gap: 22px; }
  h2 { font-size: 24px; }
  .sub { font-size: 16px; }
  .paste { flex: 1; }
  textarea { min-height: 160px; font-size: 13px; }
  .note { padding: 14px 16px; }
  .note p { font-size: 15px; }
  .submit { padding: 16px; font-size: 16px; }
  .result { padding: 40px 8px; gap: 16px; }
  .result-icon { width: 84px; height: 84px; }
  .result h2 { font-size: 28px; }
  .result p { font-size: 18px; }
}
