/* Taban Studio — taban.studio */

@font-face {
  font-family: 'Clash Display';
  src: url('assets/fonts/ClashDisplay-Medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Clash Display';
  src: url('assets/fonts/ClashDisplay-Semibold.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

:root {
  --ground: #FDFCF9;
  --ink: #14120E;
  --ink-soft: #6E6A63;
  --sun: #E8A020;
  --sun-deep: #9A650A;
  --sun-wash: #FBF0DC;
  --line: #E9E5DD;
  --card: #FFFFFF;

  --word: clamp(4rem, 15vw, 7rem);

  --display: 'Clash Display', ui-sans-serif, system-ui, sans-serif;
  --body: system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}

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

body, h1, h2, p, ul, li, figure { margin: 0; padding: 0; }

ul { list-style: none; }

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

html { -webkit-text-size-adjust: 100%; }

body {
  background: var(--ground);
  color: var(--ink);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

::selection {
  background: rgba(232, 160, 32, 0.24);
}

:focus-visible {
  outline: 2px solid var(--sun);
  outline-offset: 3px;
  border-radius: 3px;
}

/* --- Signature: warm light falling across the top of the page --- */

.sunrise {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: min(75vh, 720px);
  /* Behind the page content, so nothing above it needs its own stacking context
     — that keeps the masthead free to position against the viewport. */
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(105% 76% at 38% -10%, rgba(232, 160, 32, 0.26) 0%, rgba(232, 160, 32, 0.08) 36%, rgba(232, 160, 32, 0) 70%),
    radial-gradient(60% 44% at 88% 4%, rgba(232, 160, 32, 0.10) 0%, rgba(232, 160, 32, 0) 62%);
}

/* Full-height column so the footer closes the page on tall windows instead of
   leaving the bottom half as bare ground. main's bottom margin is the minimum
   gap above the footer; the footer's auto margin absorbs whatever is left. */
.shell {
  display: flex;
  flex-direction: column;
  min-height: 100svh;
  max-width: 680px;
  margin: 0 auto;
  /* Top padding has to clear the corner mark: around 700px wide the column sits
     directly under it, so the minimum here is what keeps them apart. */
  padding: clamp(5.5rem, 9vh, 6.5rem) 1.5rem 3rem;
}

main {
  flex: 1 0 auto;
  margin-bottom: clamp(3.5rem, 8vh, 5rem);
}

/* --- Hero --- */

/* Identity mark in the window's top-left corner. No ancestor between it and the
   page is positioned, so it anchors to the viewport rather than to the centred
   column — the same corner at every width, without any 100vw arithmetic (which
   would count the scrollbar and push it off by a few pixels).

   The offsets correct for the artwork's own padding: inside the cropped box the
   letter starts 6.3% down and 39.5% across. Both are subtracted, so --gutter
   describes where the visible letter lands, not where the box does — and the
   flare, which occupies that left 39.5%, always has room to fade out instead of
   being sliced by the window edge. --gutter must stay above --mw * 0.395 for
   that to hold. */
.masthead {
  --mw: 68px;
  --gutter: 2rem;
  position: absolute;
  top: calc(var(--gutter) - var(--mw) * 0.0357);
  left: calc(var(--gutter) - var(--mw) * 0.395);
  display: block;
  line-height: 0;
  border-radius: 4px;
}

.logo-mark {
  width: var(--mw);
  height: auto;
  display: block;
}

.wordmark {
  font-family: var(--display);
  font-weight: 600;
  font-size: var(--word);
  line-height: 0.86;
  letter-spacing: -0.045em;
}

/* Sized up from the smallest type on the page: it sits in the hero's most
   prominent position, so it needs to read as a caption, not as fine print
   under the wordmark. */
.etymology {
  margin-top: 1.125rem;
  font-size: 1rem;
  letter-spacing: 0.01em;
  color: var(--ink-soft);
}

.etymology [lang='fa'] {
  font-size: 1.1em;
  color: var(--ink);
}

.etymology .dash {
  padding: 0 0.15em;
  color: var(--sun);
}

.lede {
  margin-top: 1.75rem;
  max-width: 42ch;
  font-size: clamp(1.1875rem, 2vw, 1.4375rem);
  line-height: 1.5;
  letter-spacing: -0.011em;
}

/* --- Sections --- */

.section {
  margin-top: clamp(3.5rem, 8vh, 5rem);
}

.section-label {
  display: flex;
  align-items: center;
  gap: 1rem;
  font-family: var(--display);
  font-weight: 500;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--ink-soft);
}

/* The beam: the same gesture as the crossbar in the mark. Ignites next to the
   label and falls away across the column, so the rule marks hierarchy and
   carries the brand instead of just dividing space. */
.section-label::after {
  content: '';
  flex: 1;
  height: 1px;
  background: linear-gradient(
    90deg,
    var(--sun) 0%,
    rgba(232, 160, 32, 0.30) 14%,
    var(--line) 46%,
    rgba(233, 229, 221, 0) 100%
  );
}

/* --- Apps --- */

.app-grid {
  margin-top: 1.75rem;
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

.app-link {
  display: flex;
  align-items: flex-start;
  gap: 1.125rem;
  height: 100%;
  padding: 1.5rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 14px;
  color: inherit;
  text-decoration: none;
  transition: border-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
}

.app-link:hover {
  border-color: rgba(232, 160, 32, 0.55);
  transform: translateY(-2px);
  box-shadow: 0 10px 26px -14px rgba(26, 25, 23, 0.25);
}

.app-link:hover .app-name {
  color: var(--sun-deep);
}

.app-link:hover .app-arrow {
  color: var(--sun-deep);
  transform: translate(2px, -2px);
}

/* The app's own icon artwork, shown at 60px rather than a smaller tile: the
   WhoFlopped mark carries its own margin and is also the real App Store icon,
   so it can't be redrawn tighter — the slot grows instead.

   The radius sits just inside the 18.75% rounding drawn into that artwork, so
   it never clips it, and still rounds any future icon that arrives square. */
.app-icon {
  flex: none;
  width: 60px;
  height: 60px;
  border-radius: 11px;
  object-fit: cover;
}

.app-body {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

/* The name row spans the body, so the arrow lands in the card's top-right
   corner — the click affordance the card otherwise lacks, and a cue that the
   link leaves the site. It also gives the empty right side something to hold. */
.app-name {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.125rem;
  letter-spacing: -0.008em;
  transition: color 0.2s ease;
}

.app-arrow {
  flex: none;
  font-family: var(--body);
  font-weight: 400;
  font-size: 1rem;
  color: var(--ink-soft);
  transition: transform 0.2s ease, color 0.2s ease;
}

.app-desc {
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--ink-soft);
}

.app-platforms {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin-top: 0.25rem;
}

.badge {
  padding: 0.1875rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* --- About --- */

.about {
  display: flex;
  align-items: flex-start;
  gap: 1.25rem;
  margin-top: 1.75rem;
}

/* The ring gives the circle an edge instead of letting it dissolve into the
   page ground, and still frames a real photo once one replaces the initials. */
.avatar {
  flex: none;
  width: 80px;
  height: 80px;
  border-radius: 50%;
  object-fit: cover;
  /* Shows through while the photo loads. */
  background: var(--sun-wash);
  /* A border, not an inset shadow — an inset shadow paints below replaced
     content and would be hidden by the image itself. */
  border: 1px solid rgba(232, 160, 32, 0.28);
}

.about-name {
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.1875rem;
  letter-spacing: -0.008em;
}

.social {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  margin-top: 1.125rem;
}

.social a {
  font-size: 1rem;
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--sun);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 5px;
  transition: text-decoration-thickness 0.15s ease;
}

.social a:hover {
  text-decoration-thickness: 3px;
}

/* --- Footer --- */

.footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  /* auto, not a fixed gap: main carries the minimum separation, so this only
     absorbs the slack on a window taller than the content. */
  margin-top: auto;
  padding-top: 2rem;
  /* Same beam as the section rules, run the other way so the page closes on
     the light it opened with. */
  border-top: 1px solid transparent;
  border-image: linear-gradient(
      90deg,
      rgba(233, 229, 221, 0) 0%,
      var(--line) 46%,
      rgba(232, 160, 32, 0.30) 86%,
      var(--sun) 100%
    ) 1;
}

/* Reserve the revealed width up front so clicking "Reveal email" resolves in
   place instead of shoving the copyright sideways (and re-wrapping on narrow). */
.email {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  min-width: min(100%, 20rem);
  min-height: 2.375rem;
}

.reveal,
.copy {
  font-family: inherit;
  font-size: 0.875rem;
  color: var(--ink);
  background: transparent;
  border: 1px solid rgba(232, 160, 32, 0.45);
  border-radius: 999px;
  padding: 0.5rem 1rem;
  cursor: pointer;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}

.reveal:hover,
.copy:hover {
  border-color: rgba(232, 160, 32, 0.6);
  background: #FFF9EE;
}

/* Secondary to the address it sits beside, so it keeps the neutral border. */
.copy {
  padding: 0.375rem 0.75rem;
  font-size: 0.8125rem;
  color: var(--ink-soft);
  border-color: var(--line);
}

.email-address {
  font-size: 0.9375rem;
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--sun);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 5px;
}

.noscript-note,
.copyright {
  font-size: 0.8125rem;
  color: var(--ink-soft);
}

/* --- Motion: one orchestrated entrance, nothing else --- */

@keyframes rise {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}

.hero > * {
  animation: rise 0.7s cubic-bezier(0.2, 0.7, 0.3, 1) both;
}

.hero .wordmark  { animation-delay: 0.09s; }
.hero .etymology { animation-delay: 0.18s; }
.hero .lede      { animation-delay: 0.27s; }

.sunrise {
  animation: fade 1.4s ease-out both;
}

@keyframes fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* --- Narrow screens --- */

/* On phones the corner gutter drops to the shell's own 1.5rem, which lands the
   mark's letter exactly on the wordmark's stem below it. */
@media (max-width: 43rem) {
  .masthead {
    --mw: 60px;
    --gutter: 1.5rem;
  }
}

@media (max-width: 30rem) {
  .about {
    flex-direction: column;
    gap: 1.125rem;
  }

  .footer {
    flex-direction: column;
    align-items: flex-start;
  }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }

  .app-link:hover {
    transform: none;
  }

  .app-link:hover .app-arrow {
    transform: none;
  }
}
