chore: init

This commit is contained in:
Nick 2025-10-01 19:51:55 -05:00
commit 1b2c1ea359
891 changed files with 37053 additions and 0 deletions

View file

@ -0,0 +1,10 @@
module Config.Helpers.Response exposing (..)
import Config.Style.Colour.Helpers exposing (..)
import Element as E exposing (..)
import Element.Background as B exposing (color)
import Html.Attributes exposing (style)
dummy =
[]

View file

@ -0,0 +1,16 @@
module Config.Helpers.Viewport exposing
( Msg
, resetViewport
)
import Browser.Dom as Dom exposing (setViewport)
import Task exposing (attempt)
type Msg
= NoOp
resetViewport : Cmd Msg
resetViewport =
Task.attempt (\_ -> NoOp) (Dom.setViewportOf "scroll-container" 0 0)

View file

@ -0,0 +1,88 @@
module Config.Style.Colour.Helpers exposing
( darkColourTheme
, getColour
, getColourScheme
, getScheme
, lightColourTheme
)
import Config.Style.Colour.Types
exposing
( ColourScheme
, Theme(..)
)
import Element as E exposing (..)
import Element.Font as F exposing (color)
import Shared
lightColourTheme : ColourScheme
lightColourTheme =
{ -- Core brand colors
primary = rgb255 92 128 105 -- ll green
, secondary = rgb255 92 128 105 -- ll green
-- Surface colorsc
, background = rgb255 192 228 205 --3lite green--
, surface = rgb255 239 255 252 -- white green
, surfaceVariant = rgb255 229 255 242 -- dwhite green
-- Text colors
, onPrimary = rgb255 255 255 255
, onSecondary = rgb255 255 255 255
, onBackground = rgb255 72 108 85 -- l green
, onSurface = rgb255 32 68 45 -- m green
-- Special purpose
, shadow = rgba 34 139 34 0.15
, overlay = rgba 27 94 27 0.6
, border = rgb255 200 230 201
, focus = rgb255 102 187 106
, transparent = rgba 0 0 0 0
}
darkColourTheme : ColourScheme
darkColourTheme =
{ -- Core brand colors
primary = rgb255 92 128 105 -- ll green (unchanged)
, secondary = rgb255 32 68 45 -- g green (slightly deeper)
-- Surface colors
, background = rgb255 2 38 15 -- darker dk dk green
, surface = rgb255 18 50 28 -- dk green (slightly lighter than background)
, surfaceVariant = rgb255 38 78 50 -- mm green (lighter for contrast)
-- Text colors
, onPrimary = rgb255 92 128 105 -- ll green (unchanged)
, onSecondary = rgb255 122 168 145 -- lll green (slightly lighter for contrast)
, onBackground = rgb255 152 188 165 -- dlite green (brighter for clarity)
, onSurface = rgb255 102 138 115 -- medium green (brighter than before)
-- Special purpose
, shadow = rgba 0 0 0 0.4
, overlay = rgba 0 0 0 0.7
, border = rgb255 66 90 66 -- slightly darker than before
, focus = rgb255 129 199 132 -- unchanged
, transparent = rgba 0 0 0 0
}
getColourScheme : Theme -> ColourScheme
getColourScheme theme =
case theme of
Light ->
lightColourTheme
Dark ->
darkColourTheme
getColour : Theme -> (ColourScheme -> Color) -> Color
getColour theme colourAccessor =
colourAccessor (getColourScheme theme)
getScheme : Shared.Model -> ColourScheme
getScheme shared =
getColourScheme shared.theme

View file

@ -0,0 +1,60 @@
module Config.Style.Colour.Types exposing
( ColourScheme
, Theme(..)
, themeFromString
, themeToString
)
import Element exposing (Color)
import Json.Decode as D
import Json.Encode as E
type alias ColourScheme =
{ -- Core brand colors
primary : Color
, secondary : Color
-- Surface colors
, background : Color
, surface : Color
, surfaceVariant : Color
-- Text colors
, onPrimary : Color
, onSecondary : Color
, onBackground : Color
, onSurface : Color
-- Special purpose
, shadow : Color
, overlay : Color
, border : Color
, focus : Color
, transparent : Color
}
type Theme
= Light
| Dark
themeToString : Theme -> String
themeToString theme =
case theme of
Light ->
"light"
Dark ->
"dark"
themeFromString : String -> Theme
themeFromString str =
case str of
"dark" ->
Dark
_ ->
Light

View file

@ -0,0 +1,79 @@
module Config.Style.Fonts exposing
( FontScale
, FontSizes
, bodyFont
, createFontScale
, createFontSizes
, defaultFontScale
, headerFont
, paragraphSpacing
)
import Element
exposing
( Attr
, Attribute
, spacing
)
import Element.Font as F
exposing
( size
, typeface
)
headerFont : F.Font
headerFont =
F.typeface "Montez"
bodyFont : F.Font
bodyFont =
F.typeface "Playpen Sans"
paragraphSpacing : Attribute msg
paragraphSpacing =
spacing 0
type FontScale
= FontScale Float
createFontScale : Float -> FontScale
createFontScale baseFontSize =
FontScale baseFontSize
defaultFontScale : FontScale
defaultFontScale =
FontScale 16.0
type alias FontSizes msg =
{ verySmall : Attribute msg
, small : Attribute msg
, normal : Attribute msg
, medium : Attribute msg
, large : Attribute msg
, extraLarge : Attribute msg
, huge : Attribute msg
}
createFontSizes : FontScale -> FontSizes msg
createFontSizes (FontScale base) =
let
scaled multiplier =
F.size (round (base * multiplier))
in
{ -- assuming a 16px base:
verySmall = scaled 0.75 -- 12px
, small = scaled 0.875 -- 14px
, normal = scaled 1.0 -- 16px
, medium = scaled 1.125 -- 18px
, large = scaled 1.25 -- 20px
, extraLarge = scaled 1.5 -- 24px
, huge = scaled 2.0 -- 32px at
}

View file

@ -0,0 +1,18 @@
module Config.Style.Glow exposing (..)
import Config.Style.Colour.Helpers exposing (..)
import Element exposing (Attr)
import Element.Border as D exposing (glow)
import Html
import Html.Attributes as H
import Shared
hoverGlow : Shared.Model -> Attr decorative msg
hoverGlow shared =
D.glow (getScheme shared).onBackground 4
itemShadow : Html.Attribute msg
itemShadow =
H.style "filter" "drop-shadow(0px 0px 4px rgba(0,0,0,1))"

View file

@ -0,0 +1,33 @@
module Config.Style.Icons.Helpers exposing (buildSvg)
import Config.Style.Icons.Types as SvgTypes
exposing
( InnerPart
, OuterPart
)
import Element as E
exposing
( Element
, el
, html
)
import Svg exposing (svg)
-- , E.explain <| Debug.todo
{- buildSvg consumes an inner record to construct most of an SVG, and an outer record to supply
any potentially varying TypedSvg.Core.Attribute msgs and wrap it in an Element.el so it can be
used by elm-ui. It provides a consistent interface for inserting SVGs into elm-ui code.
-}
buildSvg : SvgTypes.OuterPart msg -> SvgTypes.InnerPart msg -> Element msg
buildSvg outer inner =
el
outer.elementAttributes
<|
html <|
Svg.svg
(outer.svgAttributes ++ inner.svgAttributes)
inner.svg

View file

@ -0,0 +1,176 @@
module Config.Style.Icons.Icons exposing (..)
import Config.Style.Icons.Helpers as HeSvg exposing (buildSvg)
import Config.Style.Icons.Types as SvgTypes
exposing
( InnerPart
, OuterPart
)
import Element as E exposing (Element)
import Html exposing (Html)
import Svg
exposing
( path
, svg
)
import Svg.Attributes as SvgAttr
discord : SvgTypes.OuterPart msg -> Element msg
discord inner =
HeSvg.buildSvg inner
{ svgAttributes =
[ SvgAttr.viewBox "0 0 640 512"
, SvgAttr.fill "currentColor"
]
, svg =
[ path
[ SvgAttr.d "M524.5 69.8a1.5 1.5 0 0 0 -.8-.7A485.1 485.1 0 0 0 404.1 32a1.8 1.8 0 0 0 -1.9 .9 337.5 337.5 0 0 0 -14.9 30.6 447.8 447.8 0 0 0 -134.4 0 309.5 309.5 0 0 0 -15.1-30.6 1.9 1.9 0 0 0 -1.9-.9A483.7 483.7 0 0 0 116.1 69.1a1.7 1.7 0 0 0 -.8 .7C39.1 183.7 18.2 294.7 28.4 404.4a2 2 0 0 0 .8 1.4A487.7 487.7 0 0 0 176 479.9a1.9 1.9 0 0 0 2.1-.7A348.2 348.2 0 0 0 208.1 430.4a1.9 1.9 0 0 0 -1-2.6 321.2 321.2 0 0 1 -45.9-21.9 1.9 1.9 0 0 1 -.2-3.1c3.1-2.3 6.2-4.7 9.1-7.1a1.8 1.8 0 0 1 1.9-.3c96.2 43.9 200.4 43.9 295.5 0a1.8 1.8 0 0 1 1.9 .2c2.9 2.4 6 4.9 9.1 7.2a1.9 1.9 0 0 1 -.2 3.1 301.4 301.4 0 0 1 -45.9 21.8 1.9 1.9 0 0 0 -1 2.6 391.1 391.1 0 0 0 30 48.8 1.9 1.9 0 0 0 2.1 .7A486 486 0 0 0 610.7 405.7a1.9 1.9 0 0 0 .8-1.4C623.7 277.6 590.9 167.5 524.5 69.8zM222.5 337.6c-29 0-52.8-26.6-52.8-59.2S193.1 219.1 222.5 219.1c29.7 0 53.3 26.8 52.8 59.2C275.3 311 251.9 337.6 222.5 337.6zm195.4 0c-29 0-52.8-26.6-52.8-59.2S388.4 219.1 417.9 219.1c29.7 0 53.3 26.8 52.8 59.2C470.7 311 447.5 337.6 417.9 337.6z"
]
[]
]
}
twitter : SvgTypes.OuterPart msg -> Element msg
twitter inner =
HeSvg.buildSvg inner
{ svgAttributes =
[ SvgAttr.viewBox "0 0 512 512"
, SvgAttr.fill "currentColor"
]
, svg =
[ path
[ SvgAttr.d "M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8L200.7 275.5 26.8 48H172.4L272.9 180.9 389.2 48zM364.4 421.8h39.1L151.1 88h-42L364.4 421.8z"
]
[]
]
}
facebook : SvgTypes.OuterPart msg -> Element msg
facebook inner =
HeSvg.buildSvg inner
{ svgAttributes =
[ SvgAttr.viewBox "0 0 640 640"
, SvgAttr.fill "currentColor"
]
, svg =
[ path
[ SvgAttr.d "M240 363.3L240 576L356 576L356 363.3L442.5 363.3L460.5 265.5L356 265.5L356 230.9C356 179.2 376.3 159.4 428.7 159.4C445 159.4 458.1 159.8 465.7 160.6L465.7 71.9C451.4 68 416.4 64 396.2 64C289.3 64 240 114.5 240 223.4L240 265.5L174 265.5L174 363.3L240 363.3z"
]
[]
]
}
tiktok : SvgTypes.OuterPart msg -> Element msg
tiktok inner =
HeSvg.buildSvg inner
{ svgAttributes =
[ SvgAttr.viewBox "0 0 640 640"
, SvgAttr.fill "currentColor"
]
, svg =
[ path
[ SvgAttr.d "M544.5 273.9C500.5 274 457.5 260.3 421.7 234.7L421.7 413.4C421.7 446.5 411.6 478.8 392.7 506C373.8 533.2 347.1 554 316.1 565.6C285.1 577.2 251.3 579.1 219.2 570.9C187.1 562.7 158.3 545 136.5 520.1C114.7 495.2 101.2 464.1 97.5 431.2C93.8 398.3 100.4 365.1 116.1 336C131.8 306.9 156.1 283.3 185.7 268.3C215.3 253.3 248.6 247.8 281.4 252.3L281.4 342.2C266.4 337.5 250.3 337.6 235.4 342.6C220.5 347.6 207.5 357.2 198.4 369.9C189.3 382.6 184.4 398 184.5 413.8C184.6 429.6 189.7 444.8 199 457.5C208.3 470.2 221.4 479.6 236.4 484.4C251.4 489.2 267.5 489.2 282.4 484.3C297.3 479.4 310.4 469.9 319.6 457.2C328.8 444.5 333.8 429.1 333.8 413.4L333.8 64L421.8 64C421.7 71.4 422.4 78.9 423.7 86.2C426.8 102.5 433.1 118.1 442.4 131.9C451.7 145.7 463.7 157.5 477.6 166.5C497.5 179.6 520.8 186.6 544.6 186.6L544.6 274z"
]
[]
]
}
instagram : SvgTypes.OuterPart msg -> Element msg
instagram inner =
HeSvg.buildSvg inner
{ svgAttributes =
[ SvgAttr.viewBox "0 0 640 640"
, SvgAttr.fill "currentColor"
]
, svg =
[ path
[ SvgAttr.d "M320.3 205C256.8 204.8 205.2 256.2 205 319.7C204.8 383.2 256.2 434.8 319.7 435C383.2 435.2 434.8 383.8 435 320.3C435.2 256.8 383.8 205.2 320.3 205zM319.7 245.4C360.9 245.2 394.4 278.5 394.6 319.7C394.8 360.9 361.5 394.4 320.3 394.6C279.1 394.8 245.6 361.5 245.4 320.3C245.2 279.1 278.5 245.6 319.7 245.4zM413.1 200.3C413.1 185.5 425.1 173.5 439.9 173.5C454.7 173.5 466.7 185.5 466.7 200.3C466.7 215.1 454.7 227.1 439.9 227.1C425.1 227.1 413.1 215.1 413.1 200.3zM542.8 227.5C541.1 191.6 532.9 159.8 506.6 133.6C480.4 107.4 448.6 99.2 412.7 97.4C375.7 95.3 264.8 95.3 227.8 97.4C192 99.1 160.2 107.3 133.9 133.5C107.6 159.7 99.5 191.5 97.7 227.4C95.6 264.4 95.6 375.3 97.7 412.3C99.4 448.2 107.6 480 133.9 506.2C160.2 532.4 191.9 540.6 227.8 542.4C264.8 544.5 375.7 544.5 412.7 542.4C448.6 540.7 480.4 532.5 506.6 506.2C532.8 480 541 448.2 542.8 412.3C544.9 375.3 544.9 264.5 542.8 227.5zM495 452C487.2 471.6 472.1 486.7 452.4 494.6C422.9 506.3 352.9 503.6 320.3 503.6C287.7 503.6 217.6 506.2 188.2 494.6C168.6 486.8 153.5 471.7 145.6 452C133.9 422.5 136.6 352.5 136.6 319.9C136.6 287.3 134 217.2 145.6 187.8C153.4 168.2 168.5 153.1 188.2 145.2C217.7 133.5 287.7 136.2 320.3 136.2C352.9 136.2 423 133.6 452.4 145.2C472 153 487.1 168.1 495 187.8C506.7 217.3 504 287.3 504 319.9C504 352.5 506.7 422.6 495 452z"
]
[]
]
}
patreon : SvgTypes.OuterPart msg -> Element msg
patreon inner =
HeSvg.buildSvg inner
{ svgAttributes =
[ SvgAttr.viewBox "0 0 640 640"
, SvgAttr.fill "currentColor"
]
, svg =
[ path
[ SvgAttr.d "M554 217.8C553.9 152.4 503 98.8 443.3 79.5C369.1 55.5 271.3 59 200.4 92.4C114.6 132.9 87.6 221.7 86.6 310.2C85.8 383 93 574.6 201.2 576C281.5 577 293.5 473.5 330.7 423.7C357.1 388.2 391.2 378.2 433.1 367.8C505.1 350 554.2 293.1 554.1 217.8L554 217.8z"
]
[]
]
}
reddit : SvgTypes.OuterPart msg -> Element msg
reddit inner =
HeSvg.buildSvg inner
{ svgAttributes =
[ SvgAttr.viewBox "0 0 640 640"
, SvgAttr.fill "currentColor"
]
, svg =
[ path
[ SvgAttr.d "M437 202.6C411.8 202.6 390.7 185.1 385.1 161.6C354.5 165.9 330.9 192.3 330.9 224L330.9 224.2C378.3 226 421.5 239.3 455.8 260.5C468.4 250.8 484.2 245 501.3 245C542.6 245 576 278.4 576 319.7C576 349.5 558.6 375.2 533.3 387.2C530.9 474 436.3 543.8 320.1 543.8C203.9 543.8 109.5 474.1 107 387.4C81.6 375.5 64 349.7 64 319.7C64 278.4 97.4 245 138.7 245C155.9 245 171.7 250.8 184.4 260.6C218.4 239.5 261.2 226.2 308.1 224.2L308.1 223.9C308.1 179.6 341.8 143 384.9 138.4C389.8 114.2 411.2 96 437 96C466.4 96 490.3 119.9 490.3 149.3C490.3 178.7 466.4 202.6 437 202.6zM221.5 319.3C200.6 319.3 182.6 340.1 181.3 367.2C180 394.3 198.4 405.3 219.3 405.3C240.2 405.3 255.9 395.5 257.1 368.4C258.3 341.3 242.4 319.3 221.4 319.3L221.5 319.3zM459 367.1C457.8 340 439.8 319.2 418.8 319.2C397.8 319.2 381.9 341.2 383.1 368.3C384.3 395.4 400 405.2 420.9 405.2C441.8 405.2 460.2 394.2 458.9 367.1L459 367.1zM398.9 437.9C400.4 434.3 397.9 430.2 394 429.8C371 427.5 346.1 426.2 320.2 426.2C294.3 426.2 269.4 427.5 246.4 429.8C242.5 430.2 240 434.3 241.5 437.9C254.4 468.7 284.8 490.3 320.2 490.3C355.6 490.3 386 468.7 398.9 437.9z"
]
[]
]
}
copyLink : SvgTypes.OuterPart msg -> Element msg
copyLink inner =
HeSvg.buildSvg inner
{ svgAttributes =
[ SvgAttr.viewBox "0 0 640 512"
, SvgAttr.fill "currentColor"
]
, svg =
[ path
[ SvgAttr.d "M579.8 267.7c56.5-56.5 56.5-148 0-204.5c-50-50-128.8-56.5-186.3-15.4l-1.6 1.1c-14.4 10.3-17.7 30.3-7.4 44.6s30.3 17.7 44.6 7.4l1.6-1.1c32.1-22.9 76-19.3 103.8 8.6c31.5 31.5 31.5 82.5 0 114L422.3 334.8c-31.5 31.5-82.5 31.5-114 0c-27.9-27.9-31.5-71.8-8.6-103.8l1.1-1.6c10.3-14.4 6.9-34.4-7.4-44.6s-34.4-6.9-44.6 7.4l-1.1 1.6C206.5 251.2 213 330 263 380c56.5 56.5 148 56.5 204.5 0L579.8 267.7zM60.2 244.3c-56.5 56.5-56.5 148 0 204.5c50 50 128.8 56.5 186.3 15.4l1.6-1.1c14.4-10.3 17.7-30.3 7.4-44.6s-30.3-17.7-44.6-7.4l-1.6 1.1c-32.1 22.9-76 19.3-103.8-8.6C74 372 74 321 105.5 289.5L217.7 177.2c31.5-31.5 82.5-31.5 114 0c27.9 27.9 31.5 71.8 8.6 103.9l-1.1 1.6c-10.3 14.4-6.9 34.4 7.4 44.6s34.4 6.9 44.6-7.4l1.1-1.6C433.5 260.8 427 182 377 132c-56.5-56.5-148-56.5-204.5 0L60.2 244.3z"
]
[]
]
}
sun : SvgTypes.OuterPart msg -> Element msg
sun inner =
HeSvg.buildSvg inner
{ svgAttributes =
[ SvgAttr.viewBox "0 0 512 512"
, SvgAttr.fill "currentColor"
]
, svg =
[ path
[ SvgAttr.d "M361.5 1.2c5 2.1 8.6 6.6 9.6 11.9L391 121l107.9 19.8c5.3 1 9.8 4.6 11.9 9.6s1.5 10.7-1.6 15.2L446.9 256l62.3 90.3c3.1 4.5 3.7 10.2 1.6 15.2s-6.6 8.6-11.9 9.6L391 391 371.1 498.9c-1 5.3-4.6 9.8-9.6 11.9s-10.7 1.5-15.2-1.6L256 446.9l-90.3 62.3c-4.5 3.1-10.2 3.7-15.2 1.6s-8.6-6.6-9.6-11.9L121 391 13.1 371.1c-5.3-1-9.8-4.6-11.9-9.6s-1.5-10.7 1.6-15.2L65.1 256 2.8 165.7c-3.1-4.5-3.7-10.2-1.6-15.2s6.6-8.6 11.9-9.6L121 121 140.9 13.1c1-5.3 4.6-9.8 9.6-11.9s10.7-1.5 15.2 1.6L256 65.1 346.3 2.8c4.5-3.1 10.2-3.7 15.2-1.6zM160 256a96 96 0 1 1 192 0 96 96 0 1 1 -192 0zm224 0a128 128 0 1 0 -256 0 128 128 0 1 0 256 0z"
]
[]
]
}
moon : SvgTypes.OuterPart msg -> Element msg
moon inner =
HeSvg.buildSvg inner
{ svgAttributes =
[ SvgAttr.viewBox "0 0 384 512"
, SvgAttr.fill "currentColor"
]
, svg =
[ path
[ SvgAttr.d "M223.5 32C100 32 0 132.3 0 256S100 480 223.5 480c60.6 0 115.5-24.2 155.8-63.4c5-4.9 6.3-12.5 3.1-18.7s-10.1-9.7-17-8.5c-9.8 1.7-19.8 2.6-30.1 2.6c-96.9 0-175.5-78.8-175.5-176 0-65.8 36-123.1 89.3-153.3c6.1-3.5 9.2-10.5 7.7-17.3s-7.3-11.9-14.3-12.5c-6.3-.5-12.6-.8-19-.8z"
]
[]
]
}

View file

@ -0,0 +1,28 @@
module Config.Style.Icons.Types exposing
( InnerPart
, OuterPart
)
{-| The types used for SVG management.
-}
import Element exposing (Attribute)
import Shared exposing (Model)
import Svg exposing (svg)
{-| The outer record for the SVG builder. This is explained in ../Helpers/Svg.elm.
-}
type alias OuterPart msg =
{ elementAttributes : List (Element.Attribute msg)
, sharedModel : Shared.Model
, svgAttributes : List (Svg.Attribute msg)
}
{-| The inner record for the SVG builder. This is explained in ../Helpers/Svg.elm.
-}
type alias InnerPart msg =
{ svgAttributes : List (Svg.Attribute msg)
, svg : List (Svg.Svg msg)
}

View file

@ -0,0 +1,69 @@
module Config.Style.Transitions exposing (..)
import Config.Style.Colour.Helpers exposing (..)
import Config.Style.Glow exposing (..)
import Element
exposing
( Attribute
, htmlAttribute
, mouseOver
)
import Element.Background as B exposing (color)
import Element.Border as D exposing (color)
import Element.Font as F exposing (color)
import Html.Attributes as H exposing (style)
import Shared
slowTime : String
slowTime =
"0.5s"
fastTime : String
fastTime =
"0.1s"
transition : String -> Attribute msg
transition time =
htmlAttribute <| style "transition" ("all " ++ time ++ " ease-in-out")
-- Specific transition functions for separating fast and slow properties
cardTransitions : Attribute msg
cardTransitions =
htmlAttribute <|
style "transition"
("background-color "
++ slowTime
++ " ease-in-out, "
++ "color "
++ slowTime
++ " ease-in-out, "
++ "border-color "
++ slowTime
++ " ease-in-out, "
++ "box-shadow "
++ fastTime
++ " ease-in-out, "
++ "transform "
++ fastTime
++ " ease-in-out"
)
hoverButton : Shared.Model -> Attribute msg
hoverButton shared =
mouseOver
[ B.color (getScheme shared).secondary
, F.color (getScheme shared).primary
]
imageFadeTransition : String -> Attribute msg
imageFadeTransition time =
htmlAttribute <| style "transition" ("opacity " ++ time ++ " ease-in-out")