Compare commits

...

10 Commits

4 changed files with 621 additions and 497 deletions

View File

@ -6,6 +6,7 @@
"elm-version": "0.19.1",
"dependencies": {
"direct": {
"chelovek0v/bbase64": "1.0.1",
"elm/browser": "1.0.2",
"elm/core": "1.0.5",
"elm/html": "1.0.0",
@ -14,13 +15,17 @@
"elm/url": "1.0.0",
"elm-community/array-extra": "2.6.0",
"elm-community/html-extra": "3.4.0",
"elm-community/list-extra": "8.7.0",
"elm-community/maybe-extra": "5.3.0",
"elm-community/string-extra": "4.0.1"
"elm-community/string-extra": "4.0.1",
"elm-toulouse/cbor": "1.1.0"
},
"indirect": {
"elm/bytes": "1.0.8",
"elm/regex": "1.0.0",
"elm/time": "1.0.0",
"elm/virtual-dom": "1.0.3"
"elm/virtual-dom": "1.0.3",
"elm-toulouse/float16": "1.0.1"
}
},
"test-dependencies": {

View File

@ -1,24 +1,34 @@
module Main exposing (main)
import FunkyFunktions exposing (..)
import Presets exposing (activities)
import Stickers exposing (Sticker, StickerContent(..), viewSticker)
import Array exposing (Array, get, set)
import Array.Extra as Array
import Base64.Encode as B64E
import Base64.Decode as B64D
import Browser
import Browser.Dom exposing (focus, getViewport, Viewport)
import Browser.Navigation exposing (Key)
import Browser.Navigation exposing (Key, pushUrl)
import Browser.Events exposing (onMouseMove, onMouseUp, onResize)
import Cbor exposing (CborItem(..))
import Cbor.Encode as CE
import Cbor.Decode as CD
import Html exposing (Attribute, button, div, h3, input, Html, section, text)
import Html.Attributes exposing (class, id, style, value)
import Html.Attributes exposing (class, disabled, id, style, value)
import Html.Attributes.Extra as Attributes exposing (attributeIf)
import Html.Extra exposing (viewMaybe)
import Html.Events exposing (onBlur, onClick, onInput, onMouseDown, onMouseEnter)
import Html.Lazy exposing (lazy2)
import Html.Events exposing (onBlur, onClick, onInput, onMouseDown, onMouseEnter, onMouseLeave)
import Html.Events.Extra exposing (onEnter)
import Html.Lazy exposing (lazy, lazy2)
import Json.Decode as D
import List exposing (map, singleton)
import List.Extra exposing (elemIndex, getAt)
import Maybe exposing (andThen)
import Maybe.Extra exposing (isJust)
import String exposing (fromInt, isEmpty)
import Result exposing (toMaybe)
import String exposing (dropLeft, fromInt, isEmpty, replace, toLower)
import String.Extra exposing (isBlank)
import Svg exposing (path, Svg, svg)
import Svg.Attributes exposing (d, fill, height, stroke, viewBox, width)
@ -40,7 +50,7 @@ type Msg
| Click Int Int Int Int
| SetTileText Int Int String
| AddTile Int
| TileDeselected Int
| PruneTile Int Int
| HeldOverNewTile Int Int
| NewMousePos Int Int
| StartDrag Int Int Tile Int Int
@ -50,12 +60,10 @@ type alias Model =
{ columns: Array Column
, heldTile: Maybe HeldTile
, mousePos: (Int, Int)
, browserKey: Key
}
type alias Column =
{ name: String
, tiles: Array Tile
}
type alias Column = { tiles: Array Tile }
type alias Tile =
{ text: String
@ -72,25 +80,17 @@ blankTile = { text = "", stickers = [] }
init : () -> Url -> Key -> (Model, Cmd Msg)
init flags url browserKey =
{ columns =
[ { name = "Into"
, tiles = Array.empty
}
, { name = "Willing"
, tiles = Array.empty
}
, { name = "Maybe"
, tiles = Array.empty
}
, { name = "No"
, tiles = Array.empty
}
]
|> Array.fromList
, mousePos = (200, 200)
, heldTile = Nothing
}
|> withoutCmd
let
m =
case load browserKey url of
Just model -> model
Nothing ->
{ columns = Array.repeat 4 (Column Array.empty)
, mousePos = (200, 200)
, heldTile = Nothing
, browserKey = browserKey
}
in m |> withoutCmd
subscriptions : Model -> Sub Msg
subscriptions model =
@ -109,6 +109,7 @@ subscriptions model =
view : Model -> Browser.Document Msg
view {columns, heldTile, mousePos} =
[ lazy2 viewColumns heldTile columns
, lazy viewWordbank activities
, viewMaybe (viewFloatyTile mousePos) heldTile
]
|> Browser.Document "meow!"
@ -116,11 +117,10 @@ view {columns, heldTile, mousePos} =
viewColumns : Maybe HeldTile -> Array Column -> Html Msg
viewColumns heldTile columns =
Array.indexedMap (viewColumn heldTile) columns
|> Array.map (singleton >> div [])
|> Array.toList
|> section
[ class "columns"
-- Temporary hack while firefox's :has() selector is broken
, attributeIf (isJust heldTile) <| style "user-select" "none"
]
@ -138,7 +138,7 @@ viewFloatyTile (mouseX, mouseY) { tile, hoveredColumnIndex } =
viewHoverTile = div [id "hover-tile"] []
viewColumn : Maybe HeldTile -> Int -> Column -> Html Msg
viewColumn heldOverTile columnIndex {name, tiles} =
viewColumn heldOverTile columnIndex {tiles} =
let
isTileHeld = isJust heldOverTile
tileCount = Array.length tiles
@ -157,14 +157,23 @@ viewColumn heldOverTile columnIndex {name, tiles} =
in
div
[ class "column"
, attributeIf isTileHeld (onMouseLeave <| HeldOverNewTile -1 -1)
]
( ( h3
[]
[text name]
[text <| columnIndexToName columnIndex]
) :: tilesList
++ [ viewAddTile isTileHeld columnIndex tileCount ]
)
columnIndexToName : Int -> String
columnIndexToName i = case i of
0 -> "Into"
1 -> "Willing"
2 -> "Maybe"
3 -> "No"
_ -> "Too Many Columns"
viewTile : Bool -> Int -> Int -> Tile -> Html Msg
viewTile isTileHeld columnIndex tileIndex tile =
div
@ -176,29 +185,30 @@ viewTile isTileHeld columnIndex tileIndex tile =
-- )
, attributeIf isTileHeld (onMouseEnter <| HeldOverNewTile columnIndex tileIndex)
]
[ viewGrip columnIndex tileIndex tile
[ viewGrip 24 columnIndex tileIndex tile
, input
[ value tile.text
, onInput (SetTileText columnIndex tileIndex)
, onBlur (TileDeselected columnIndex)
, attributeIf (isBlank tile.text) <| onBlur (PruneTile columnIndex tileIndex)
, attributeIf (isBlank tile.text) (id "new-tile")
, onEnter (AddTile columnIndex)
]
[]
, svg
[ Svg.Attributes.class "tile-stickers"
, height "80"
, width "400"
, height "64"
, width "320"
, style "user-select" "none"
]
(map viewSticker tile.stickers)
]
viewGrip : Int -> Int -> Tile -> Html Msg
viewGrip colIndx tileIndx tile =
viewGrip : Int -> Int -> Int -> Tile -> Html Msg
viewGrip size colIndx tileIndx tile =
svg
[ viewBox "0 0 103.4 103.4"
, width "30"
, height "30"
, width <| String.fromInt size
, height <| String.fromInt size
, Svg.Attributes.class "drag-gripper"
, on "mousedown" <| (
D.map2 (StartDrag colIndx tileIndx tile)
@ -226,6 +236,27 @@ viewAddTile isTileHeld columnIndex tileCount =
]
[ text "+" ]
viewWordbank : List String -> Html Msg
viewWordbank wordlist =
section
[ id "word-bank"
]
(map viewMiniTile wordlist)
viewMiniTile : String -> Html Msg
viewMiniTile word =
div
[ class "tile"
, class "mini-tile"
]
[ viewGrip 16 -1 -1 { text = word, stickers = [] }
, input
[ value word
, disabled True
]
[]
]
addStickerToTile : Sticker -> Tile -> Tile
addStickerToTile sticker tile =
{ tile | stickers = sticker :: tile.stickers }
@ -237,10 +268,6 @@ addTileToColumn column =
isTileEmpty : Tile -> Bool
isTileEmpty = .text >> isEmpty
pruneTiles : Column -> Column
pruneTiles column =
{ column | tiles = Array.filter (not << isTileEmpty) column.tiles }
updateTileText : String -> Tile -> Tile
updateTileText text tile =
{ tile | text = text }
@ -292,17 +319,17 @@ update msg model = case Debug.log "UPDATE" msg of
(modColumnInPage columnIndex << modTileInColumn tileIndex)
(updateTileText newText)
model
|> withoutCmd
|> withSaveCmd
AddTile columnIndex ->
modColumnInPage columnIndex
addTileToColumn
model
|> withCmd (Task.attempt (constant Noop) (focus "new-tile"))
TileDeselected columnIndex ->
PruneTile columnIndex tileIndex ->
modColumnInPage columnIndex
pruneTiles
(removeTileFromColumn tileIndex)
model
|> withoutCmd
|> withSaveCmd
HeldOverNewTile columnIndex tileIndex -> case model.heldTile of
Nothing -> model |> withoutCmd
Just oldHeldTileInfo ->
@ -353,4 +380,79 @@ update msg model = case Debug.log "UPDATE" msg of
model
in
{ modelWithTileInserted | heldTile = Nothing }
|> withoutCmd
|> withSaveCmd
withSaveCmd : Model -> (Model, Cmd Msg)
withSaveCmd model = (model, save model)
andSaveCmd : (Model, Cmd Msg) -> (Model, Cmd Msg)
andSaveCmd (model, cmd) = (model, Cmd.batch [cmd, save model])
save : Model -> Cmd Msg
save model =
saveModel model
|> CE.encode
|> B64E.bytes
|> B64E.encode
|> dropLeft 1
|> replace "=" ""
|> (++) "#"
|> pushUrl model.browserKey
load : Key -> Url -> Maybe Model
load key url =
url.fragment
|> Maybe.map ((++) "g")
|> andThen (B64D.decode B64D.bytes >> toMaybe)
|> andThen (CD.decode (loadModel key))
saveModel : Model -> CE.Encoder
saveModel { columns } =
Array.toList columns
|> map saveColumn
|> CE.sequence
array4 a b c d = Array.fromList [a, b, c, d]
loadModel : Key -> CD.Decoder Model
loadModel key =
CD.map4 array4 loadColumn loadColumn loadColumn loadColumn
|> CD.map Model
|> CD.map ((|>) Nothing)
|> CD.map ((|>) (0, 0))
|> CD.map ((|>) key)
saveColumn : Column -> CE.Encoder
saveColumn { tiles } = CE.list saveTile (Array.toList tiles)
loadColumn : CD.Decoder Column
loadColumn =
CD.list loadTile
|> CD.map Array.fromList
|> CD.map Column
saveTile : Tile -> CE.Encoder
saveTile { text } =
case elemIndex (toLower text) activities of
Just index -> CE.int index
Nothing -> CE.string text
loadTile : CD.Decoder Tile
loadTile =
CD.any
|> CD.andThen loadTileInner
loadTileInner : CborItem -> CD.Decoder Tile
loadTileInner item =
let
word =
case item of
CborInt i ->
case getAt i activities of
Just activity -> CD.succeed activity
Nothing -> CD.fail
CborString s -> CD.succeed s
_ -> CD.fail
in
CD.map (flip Tile []) word

View File

@ -9,411 +9,390 @@ type alias WordSet =
, words : List String -- e.g. Bondage, Schlong, Loss of Control
}
allWordSets = [activitiesSet, languageSet, feelingsSet]
activitiesSet = WordSet
"Activities"
(["Yes - Into", "Yes - Willing", "Maybe", "No"] |> StickerContent "black")
-- TODO make actual stickers for these
(["Top / Giver", "Bottom / Reciever", "Never Tried", "Favorite"] |> StickerContent "black")
activities
languageSet = WordSet
"Language"
(["Yes - Into", "Yes - Willing", "Maybe", "No"] |> StickerContent "black")
(["Speaker", "Listener", "Never Tried", "Favorite"] |> StickerContent "black")
language
feelingsSet = WordSet
"Feelings"
(["Often", "Sometimes", "Never"] |> StickerContent "black")
(["I like to feel", "I want my partner to feel", "Never Tried", "Favorite"] |> StickerContent "black")
activities =
[ "69"
, "Age-Play"
, "Anal Sex"
, "Analingus/Rimming"
, "Ball Stretching"
, "Being Filmed/Photographed"
, "Being Watched"
, "Biting"
, "Blindfolds"
, "Blood Play"
, "Light Bondage"
, "Heavy Bondage"
, "Rope"
, "Boot-blacking"
, "Bratting"
, "Breath Play"
, "Butt Plugs"
, "Cages/Confinement"
, "Caning"
, "Chastity"
, "Cock/Pussy Worship"
, "Cockrings"
, "Collars"
, "Consensual Non-Consent"
, "Costumes"
, "Cross Dressing"
, "Cuckolding"
, "Cuddling"
, "Cunnilingus"
, "Degradation"
, "Dirty Talk"
, "Domination"
, "Double Penetration" -- TODO Which hole(s)? note??? how do we handle this?
, "E-Stim"
, "Edging"
, "Ejaculate"
, "Enemas"
, "Eye Contact (or restriction from)"
, "Face Fucking"
, "Facesitting"
, "Fellatio"
, "Fingering" -- (External? Anal? Vaginal?)
, "Fisting" -- (Anal? Vaginal?)
, "Flogging"
, "Food Play"
, "Foot Play"
, "Frottage"
, "Furries"
, "G-Spot"
, "Gags"
, "Gender Play"
, "Genital Torture"
, "Group Sex"
, "Hair Pulling"
, "Hoods"
, "Humiliation"
, "Incest"
, "Roleplay"
, "Kicking"
, "Kidnapping"
, "Roleplay"
, "Kissing" -- (Where?)
, "Knife Play"
, "Leather"
, "Lingerie"
, "Massage"
, "Medical Play"
, "Moans"
, "Mutual Masturbation"
, "Nipple Clamps"
, "Nipple Play"
, "Nipple Torture"
, "Objectification"
, "Orgasm Control"
, "Orgasm Denial"
, "Paddles"
, "Mild Pain"
, "Moderate Pain"
, "Severe Pain"
, "Pegging"
, "Piercing"
, "Phone Sex"
, "Piss Play"
, "Porn"
, "Power Exchange"
, "Prostate Play"
, "Punching"
, "Punishment"
, "Race Play"
, "Riding Crops"
, "Role Play" -- (Which Roles?)
, "Rubber/Latex Clothing"
, "Scat"
, "Scratching"
, "Sensory Deprivation"
, "Service"
, "Sex During Menstruation"
, "Sex in Public"
, "Sex Magic"
, "Sex Parties"
, "Sex Toys"
, "Sexting"
, "Shaving"
, "Slapping" -- (Where?)
, "Smoking" -- (Cigarettes? 420? Cigars?)
, "Spanking"
, "Sploshing"
, "Spreader Bars"
, "Strap Ons"
, "Strip Clubs"
, "Submission"
, "Suspension"
, "Swallowing Ejaculate"
, "Tantra"
, "Teasing"
, "Temporary Marks"
, "Threesome" -- (Genders?)
, "Tickling"
, "Tit-Fucking"
, "Tribadism"
, "Triple Penetration"
, "Vaginal Penetration"
, "Watching Others"
, "Wax"
, "Whips"
, "Wrestling"
, "age-play"
, "anal sex"
, "analingus/rimming"
, "ball stretching"
, "being filmed/photographed"
, "being watched"
, "biting"
, "blindfolds"
, "blood play"
, "light bondage"
, "heavy bondage"
, "rope"
, "boot-blacking"
, "bratting"
, "breath play"
, "butt plugs"
, "cages/confinement"
, "caning"
, "chastity"
, "cock/pussy worship"
, "cockrings"
, "collars"
, "consensual non-consent"
, "costumes"
, "cross dressing"
, "cuckolding"
, "cuddling"
, "cunnilingus"
, "degradation"
, "dirty talk"
, "domination"
, "double penetration" -- todo which hole(s)? note??? how do we handle this?
, "e-stim"
, "edging"
, "ejaculate"
, "enemas"
, "eye contact (or restriction from)"
, "face fucking"
, "facesitting"
, "fellatio"
, "fingering" -- (external? anal? vaginal?)
, "fisting" -- (anal? vaginal?)
, "flogging"
, "food play"
, "foot play"
, "frottage"
, "furries"
, "g-spot"
, "gags"
, "gender play"
, "genital torture"
, "group sex"
, "hair pulling"
, "hoods"
, "humiliation"
, "incest"
, "roleplay"
, "kicking"
, "kidnapping"
, "roleplay"
, "kissing" -- (where?)
, "knife play"
, "leather"
, "lingerie"
, "massage"
, "medical play"
, "moans"
, "mutual masturbation"
, "nipple clamps"
, "nipple play"
, "nipple torture"
, "objectification"
, "orgasm control"
, "orgasm denial"
, "paddles"
, "mild pain"
, "moderate pain"
, "severe pain"
, "pegging"
, "piercing"
, "phone sex"
, "piss play"
, "porn"
, "power exchange"
, "prostate play"
, "punching"
, "punishment"
, "race play"
, "riding crops"
, "role play" -- (which roles?)
, "rubber/latex clothing"
, "scat"
, "scratching"
, "sensory deprivation"
, "service"
, "sex during menstruation"
, "sex in public"
, "sex magic"
, "sex parties"
, "sex toys"
, "sexting"
, "shaving"
, "slapping" -- (where?)
, "smoking" -- (cigarettes? 420? cigars?)
, "spanking"
, "sploshing"
, "spreader bars"
, "strap ons"
, "strip clubs"
, "submission"
, "suspension"
, "swallowing ejaculate"
, "tantra"
, "teasing"
, "temporary marks"
, "threesome" -- (genders?)
, "tickling"
, "tit-fucking"
, "tribadism"
, "triple penetration"
, "vaginal penetration"
, "watching others"
, "wax"
, "whips"
, "wrestling"
]
language =
[ "Abuse"
, "Aching"
, "Ample"
, "Aroused"
, "Ass"
, "Asshole"
, "Babe"
, "Baby"
, "Baby Girl/Boy"
, "Balls"
, "Bang"
, "Beat"
, "Beautiful"
, "Beg"
, "Bitch"
, "Bite"
, "Bits"
, "Blowjob"
, "Blush"
, "Bone/Boner"
, "Boobs"
, "Booty"
, "Bottom"
, "Boy/Boi"
, "Brat"
, "Breasts"
, "Bruise"
, "Bulge"
, "Blush"
, "Butt"
, "Button"
, "Choke"
, "Clit"
, "Clitoris"
, "Cock"
, "Cock Sucking"
, "Cum"
, "Cum Dumpster"
, "Cum Slut"
, "Cunnilingus"
, "Cunt"
, "Daddy"
, "Darling"
, "Destroy"
, "Dick"
, "Dirty"
, "Disappointment"
, "Disgusting"
, "Down There"
, "Dripping"
, "Eating Out"
, "Embarrassed"
, "Face Fucking"
, "Faggot"
, "Fap"
, "Fellatio"
, "Filthy"
, "Finger"
, "Finger Bang"
, "Finger Fuck"
, "Freak"
, "Fuck"
, "Fuck Toy"
, "Gag"
, "Giggle"
, "Girl"
, "Goddess"
, "Gorgeous"
, "Grab"
, "Groan"
, "Hairy"
, "Hard/Hard On"
, "Hole"
, "Honey"
, "Horny"
, "Hot"
, "Intense"
, "Jerk Off"
, "Jizz"
, "Jugs"
, "Juicy"
, "Junk"
, "Kitten"
, "Lick"
, "Lips"
, "Little"
, "Little One"
, "Load"
, "Maam"
, "Master"
, "Masturbate"
, "Member"
, "Mine"
, "Miss"
, "Mister"
, "Mistress"
, "Moan"
, "Moist"
, "Mouth"
, "Nads"
, "Nasty"
, "Nipples"
, "Pathetic"
, "Pecker"
, "Pervert"
, "Pig/Piggy"
, "Pink"
, "Please"
, "Pound"
, "Prick"
, "Princess"
, "Property"
, "Punch"
, "Pup"
, "Pussy"
, "Rape"
, "Ravage"
, "Red"
, "Rump"
, "Sack"
, "Sad"
, "Schlong"
, "Scratch"
, "Scream"
, "Screw"
, "Sexy"
, "Shiver"
, "Shoot"
, "Sir"
, "Sissy"
, "Skank"
, "Slam"
, "Slap"
, "Slave"
, "Slide"
, "Slut"
, "Smack"
, "Smooth"
, "Snatch"
, "Soft"
, "Solid"
, "Spank"
, "Spit"
, "Squeeze"
, "Strong"
, "Stupid"
, "Suck"
, "Sweet"
, "Sweetheart"
, "Tease"
, "Teeth"
, "Tight"
, "Tits"
, "Top"
, "Toy"
, "Tramp"
, "Turgid"
, "Twat"
, "Vag"
, "Vagina"
, "Vixen"
, "Vulva"
, "Wad"
, "Wang"
, "Wank"
, "Watch"
, "Wet"
, "Whimper"
, "Whore"
, "Worthless"
[ "abuse"
, "aching"
, "ample"
, "aroused"
, "ass"
, "asshole"
, "babe"
, "baby"
, "baby girl/boy"
, "balls"
, "bang"
, "beat"
, "beautiful"
, "beg"
, "bitch"
, "bite"
, "bits"
, "blowjob"
, "blush"
, "bone/boner"
, "boobs"
, "booty"
, "bottom"
, "boy/boi"
, "brat"
, "breasts"
, "bruise"
, "bulge"
, "blush"
, "butt"
, "button"
, "choke"
, "clit"
, "clitoris"
, "cock"
, "cock sucking"
, "cum"
, "cum dumpster"
, "cum slut"
, "cunnilingus"
, "cunt"
, "daddy"
, "darling"
, "destroy"
, "dick"
, "dirty"
, "disappointment"
, "disgusting"
, "down there"
, "dripping"
, "eating out"
, "embarrassed"
, "face fucking"
, "faggot"
, "fap"
, "fellatio"
, "filthy"
, "finger"
, "finger bang"
, "finger fuck"
, "freak"
, "fuck"
, "fuck toy"
, "gag"
, "giggle"
, "girl"
, "goddess"
, "gorgeous"
, "grab"
, "groan"
, "hairy"
, "hard/hard on"
, "hole"
, "honey"
, "horny"
, "hot"
, "intense"
, "jerk off"
, "jizz"
, "jugs"
, "juicy"
, "junk"
, "kitten"
, "lick"
, "lips"
, "little"
, "little one"
, "load"
, "maam"
, "master"
, "masturbate"
, "member"
, "mine"
, "miss"
, "mister"
, "mistress"
, "moan"
, "moist"
, "mouth"
, "nads"
, "nasty"
, "nipples"
, "pathetic"
, "pecker"
, "pervert"
, "pig/piggy"
, "pink"
, "please"
, "pound"
, "prick"
, "princess"
, "property"
, "punch"
, "pup"
, "pussy"
, "rape"
, "ravage"
, "red"
, "rump"
, "sack"
, "sad"
, "schlong"
, "scratch"
, "scream"
, "screw"
, "sexy"
, "shiver"
, "shoot"
, "sir"
, "sissy"
, "skank"
, "slam"
, "slap"
, "slave"
, "slide"
, "slut"
, "smack"
, "smooth"
, "snatch"
, "soft"
, "solid"
, "spank"
, "spit"
, "squeeze"
, "strong"
, "stupid"
, "suck"
, "sweet"
, "sweetheart"
, "tease"
, "teeth"
, "tight"
, "tits"
, "top"
, "toy"
, "tramp"
, "turgid"
, "twat"
, "vag"
, "vagina"
, "vixen"
, "vulva"
, "wad"
, "wang"
, "wank"
, "watch"
, "wet"
, "whimper"
, "whore"
, "worthless"
]
feelings =
[ "Abandoned"
, "Accomplished"
, "Adored"
, "Animalistic"
, "Anger"
, "Ashamed"
, "Bad"
, "Belonging"
, "Big"
, "Catharsis"
, "Cherished"
, "Clever"
, "Coerced"
, "Competent"
, "Connected"
, "Corrupted"
, "Defeated"
, "Desired"
, "Dirty"
, "Disrespected"
, "Dutiful"
, "Embarrassed"
, "Encouraged"
, "Euphoric"
, "Fear"
, "Focused"
, "Forced"
, "Forgiveness"
, "Free"
, "Good"
, "Helplessness"
, "Humiliation"
, "Humility"
, "Idolized"
, "Impressed"
, "Infantilized"
, "Innocent"
, "Loss of Control"
, "Loved"
, "Lust"
, "Mean"
, "Neediness"
, "Nurturing"
, "Objectified"
, "Open"
, "Out of Control"
, "Overpowered"
, "Overwhelmed"
, "Owned"
, "Passivity"
, "Pathos"
, "Perverted"
, "Pity"
, "Powerful"
, "Protected"
, "Punished"
, "Rebellious"
, "Rebellious"
, "Redemption"
, "Resentment"
, "Redeemed"
, "Resentment"
, "Respected"
, "Sadistic"
, "Sadness"
, "Safe"
, "Satiated"
, "Served"
, "Sexy"
, "Small"
, "Special"
, "Strong"
, "Submissive"
, "Subservient"
, "Trust"
, "Used"
, "Useful"
, "Victimized"
, "Violated"
, "Wanted"
, "Worshiped"
, "Worthless"
, "Wrong"
[ "abandoned"
, "accomplished"
, "adored"
, "animalistic"
, "anger"
, "ashamed"
, "bad"
, "belonging"
, "big"
, "catharsis"
, "cherished"
, "clever"
, "coerced"
, "competent"
, "connected"
, "corrupted"
, "defeated"
, "desired"
, "dirty"
, "disrespected"
, "dutiful"
, "embarrassed"
, "encouraged"
, "euphoric"
, "fear"
, "focused"
, "forced"
, "forgiveness"
, "free"
, "good"
, "helplessness"
, "humiliation"
, "humility"
, "idolized"
, "impressed"
, "infantilized"
, "innocent"
, "loss of control"
, "loved"
, "lust"
, "mean"
, "neediness"
, "nurturing"
, "objectified"
, "open"
, "out of control"
, "overpowered"
, "overwhelmed"
, "owned"
, "passivity"
, "pathos"
, "perverted"
, "pity"
, "powerful"
, "protected"
, "punished"
, "rebellious"
, "rebellious"
, "redemption"
, "resentment"
, "redeemed"
, "resentment"
, "respected"
, "sadistic"
, "sadness"
, "safe"
, "satiated"
, "served"
, "sexy"
, "small"
, "special"
, "strong"
, "submissive"
, "subservient"
, "trust"
, "used"
, "useful"
, "victimized"
, "violated"
, "wanted"
, "worshiped"
, "worthless"
, "wrong"
]

View File

@ -3,35 +3,38 @@ button
h3
font-family: 'Rent Strike'
font-size: 5em
margin: 30px
font-size: 4em
margin: 24px
input
font-family: 'Rent Strike'
font-size: 1.5em
font-size: 1.2em
.columns
display: flex
flex-flow: row wrap
justify-content: center
overflow-y: auto
& > :nth-child(4n+1)
--color-strong: #c0d694
--color-weak: #e5eed4
& > :nth-child(4n+2)
--color-strong: #6ed8d6
--color-weak: #d3f3f2
& > :nth-child(4n+3)
--color-strong: #d3aee1
--color-weak: #eddef3
& > :nth-child(4n+4)
--color-strong: #eeab87
--color-weak: #f9e5db
.column
width: 400px
padding: 20px
&:nth-child(4n+1)
--color-strong: #c0d694
--color-weak: #e5eed4
&:nth-child(4n+2)
--color-strong: #6ed8d6
--color-weak: #d3f3f2
&:nth-child(4n+3)
--color-strong: #d3aee1
--color-weak: #eddef3
&:nth-child(4n+4)
--color-strong: #eeab87
--color-weak: #f9e5db
width: 320px
padding: 64px
& > h3
color: var(--color-strong)
@ -42,46 +45,62 @@ input
text-align: center
#hover-tile
height: 110px
margin-top: -15px
height: 88px
margin-top: -12px
.tile
position: relative
height: 80px
width: 400px
height: 64px
width: 320px
display: grid
align-items: center
margin-bottom: 15px
margin-bottom: 12px
border: none
background-color: var(--color-weak)
&.mini-tile
height: 40px
width: 200px
margin: 10px
--color-strong: #999
--color-weak: #ccc
svg.drag-gripper
padding: 5px
top: 7px
left: 5px
input
font-size: 1.36em
color: black
svg.drag-gripper
color: var(--color-strong)
position: absolute
padding: 8px
top: 17px // Centered in 80px with 30px body and 8px padding
left: 15px
border-radius: 8px
padding: 6px
top: 14px // Centered in 64px with 24px body and 6px padding
left: 12px
cursor: grab
&::after
width: 400px
height: 20px
width: 320px
height: 64px
content: ''
position: absolute
top: -20px
top: -12px
z-index: -1 // Prevent fluttering when moving mouse up
input
padding: 20px
margin: 0
height: 40px
padding: 0
padding-top: 6px
height: calc(100% - 6px)
width: 100%
background: none
border: none
text-align: center
font-size: 2.6em
width: 360px
font-size: 2.1em
&:focus-visible
border: none
@ -96,12 +115,13 @@ input
padding: 0
text-align: center
font-weight: bold
font-size: 80px
font-size: 64px
color: white
line-height: 0
#floaty-tile
position: absolute
pointer-events: none
&.hovering-1 > .tile
--color-weak: #e5eed4
@ -121,11 +141,29 @@ input
& > .tile
position: relative
top: -40px
left: -40px
pointer-events: none
top: -32px
left: -30px
// Disable selection while dragging a tile
// broken on latest firefox tho
body:has( > #floaty-tile)
user-select: none
--color-strong: #999
--color-weak: #ccc
#word-bank
width: calc(100% - 400px)
padding: 30px 200px
display: flex
flex-flow: row wrap
justify-content: space-around
overflow-y: auto
overflow-x: hidden
background-color: #eee
body
user-select: none
display: grid
grid-template-rows: 1fr 20%
height: 100%
position: absolute
margin: 0